別にRailsではなくても純粋なRubyでも基本的には同じ。
module Fuga
def self.included base
base.extend ClassMethods
end
module ClassMethods
def hello
puts 'Hello!'
end
end
end
Fugamoduleがインクルードされた時に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
このFugamoduleを任意の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
上記のように、AddDelatedmoduleを作成して、ActiveRecord::Baseを再オープンしてAddDelatedをincludeするとActiveRecord::Baseを継承するクラスでadd_deletedが使えるようになります。
add_deletedが呼ばれたクラスでは、attr_accessorにdeletedが追加されます。