RailsのActiveSupport::Concernで何が行われているか
ActiveSupport::Concern を使わない場合の concern の書き方について、公式ドキュメントをみながら、何が行われているのか見てみました。
デフォルトでは rails はapp/{controllers,models}/concerns を自動で読み込むモードになっているのでConcerns::のような名前空間をつける必要はありません。(参考: 公式ドキュメント)
concern の使い方としては読み込み先のクラスで、include Mでモジュールを読み込むと、included do..endの中のメソッドがインスタンスメソッドまたはクラスメソッドとして読み込まれます。
インスタンスメソッドならdef sum ... end、クラスメソッドならdef self.sum ... end
また、class_methodsに書いたメソッドはクラスメソッドとして拡張されます。
これをどうやって実現しているか見ていきます!!
ActiveSupport::Concern を使う場合、使わない場合、を記載して使わない場合のコードについて一つづつ見ていきます!
require "active_support/concern"
module M
extend ActiveSupport::Concern
included do
scope :disabled, -> { where(disabled: true) }
end
class_methods do
...
end
endmodule M
def self.included(base)
base.extend ClassMethods
base.class_eval do
scope :disabled, -> { where(disabled: true) }
end
end
module ClassMethods
...
end
endこちら、公式ドキュメントよりモジュールを読み込んだ時に発動するメソッドだと解ります。
つまり、include M とするとこのクラスメソッドが読み込み先のクラスで発動しbaseには読み込み先のクラスが入ってきます。
読み込み先のクラスであるbaseがClassMethodsというモジュールを拡張して、ClassMethodsに書いてあるメソッドをbaseがクラスメソッドとして使えるようになります。
baseに中のインスタンスメソッドまたはクラスメソッドを追加しています。
ちなみに、scopeはクラスメソッドと同じように振る舞いますがifのような条件文を使う場合は注意が必要なようです。
今回の記事は以上になります!読んでいただいてありがとうございます!
解りにくいところ、間違っているところなどあれば連絡いただければと思います。
何か連絡をしたい際は以下 SNS、メールでお願いいたします。
Twitter: https://twitter.com/naka_ryo_z