別にRailsではなくても純粋なRubyでも基本的には同じ。
module Fuga
def self.included base
base.extend ClassMethods
end
module ClassMethods
def hello
puts 'Hello!'
end
end
end
Fuga
moduleがインクルードされた時にClassMethods
で定義さていているメソッドが使えるようになる。
下記のようにすれば、インスタンスメソッドも追加出来ます。
module Fuga
def self.included base
base.extend ClassMethods
end
module ClassMethods
def hello
puts 'Hello!'
end
end
#以下追加
def bar
puts "bar"
end
end
このFuga
moduleを任意のClassにincludeすれば、hello
がクラスマクロとして使用できるようになります。
class Bar
include Fuga
hello
end
これはextendを使って書き換えることができます。
module Fuga
def hello
puts 'Hello!'
end
end
class Bar
extend Fuga
hello
end
extend
で呼ぶ出すとクラスメソッドとして定義されます。
ActiveSupport::Concern
をextendしてくると、def self.included end
の部分を省略できます。
module Fuga
extend ActiveSupport::Concern
module ClassMethods
def hello
puts 'Hello!'
end
end
end
これで任意のクラスでFuga
をincludeすれば、hello
がクラスマクロとして使えるようになります。
ここからがRailsの話し。
module AddDeleted
extend ActiveSupport::Concern
module ClassMethods
def add_deleted
attr_accessor: :deleted
end
end
end
class ActiveRecord::Base
include AddDeleted
end
class Book < ActiveRecord::Base
add_deleted
end
上記のように、AddDelated
moduleを作成して、ActiveRecord::Base
を再オープンしてAddDelated
をincludeするとActiveRecord::Base
を継承するクラスでadd_deleted
が使えるようになります。
add_deleted
が呼ばれたクラスでは、attr_accessor
にdeleted
が追加されます。