Closed3

忘れがちなRubyのincludedに関するメモ

machampmachamp
module M
  def self.included(base)
    base.extend(ClassMethods)
  end

  module ClassMethods
    def foo
      puts 'foo'
    end
  end
  
  def bar
    puts 'bar'
  end
end

このモジュールを include するとクラスメソッドとして foo が、
インスタンスメソッドとして bar が使える様になる。

class C
  include M
end

C.foo #=> foo

C.new.bar #=> bar
machampmachamp

ActiveSupport::Concern を使うとシンプルに書くことが出来る。

module M
  extend ActiveSupport::Concern

  module ClassMethods
    def foo
      puts 'foo'
    end
  end

  def bar
    puts 'bar'
  end
end
machampmachamp

include元のクラスメソッドを呼び出すパターン

module LogicalDeleteScopes
  def self.included(base)
    base.class_eval(base) do
      scope :without_deleted, lambda { where(deleted_at: nil }
    end
  end
end

class Article < ActiveRecord::Base
  include LogicalDeleteScopes
end

このモジュールは ActiveRecord を継承したクラスに include されることを期待している。
def self.included(base) は、モジュールが include されたときに対象のクラスがまたはモジュールを引数にしてインタプリタがこのメソッドを呼び出す。

class_eval は、モジュールのコンテキストで文字列またはブロックを評価してその結果を返す。

module LogicalDeleteScopes
  extend ActiveSupport::Concern

  included do
    scope :without_deleted, lambda { where(deleted_at: nil }
  end
end

Concern を使って書き換えるとこの様になる。

このスクラップは2ヶ月前にクローズされました