top_logo

RailsのActiveSupport::Concernで何が行われているか

2022年 04月 04日

ActiveSupport::Concern を使わない場合の concern の書き方について、公式ドキュメントをみながら、何が行われているのか見てみました。


デフォルトでは rails はapp/{controllers,models}/concerns を自動で読み込むモードになっているのでConcerns::のような名前空間をつける必要はありません。(参考: 公式ドキュメント)



ActiveSupport を使う場合と使わない場合の比較

concern の使い方としては読み込み先のクラスで、include Mでモジュールを読み込むと、included do..endの中のメソッドがインスタンスメソッドまたはクラスメソッドとして読み込まれます。


インスタンスメソッドならdef sum ... end、クラスメソッドならdef self.sum ... end


また、class_methodsに書いたメソッドはクラスメソッドとして拡張されます。


これをどうやって実現しているか見ていきます!!


ActiveSupport::Concern を使う場合、使わない場合、を記載して使わない場合のコードについて一つづつ見ていきます!

ActiveSupport を使う場合
require "active_support/concern"

module M
  extend ActiveSupport::Concern

  included do
    scope :disabled, -> { where(disabled: true) }
  end

  class_methods do
    ...
  end
end

ActiveSupport を使わない場合
module M
  def self.included(base)
    base.extend ClassMethods
    base.class_eval do
      scope :disabled, -> { where(disabled: true) }
    end
  end

  module ClassMethods
    ...
  end
end

def self.included(base) … end

こちら、公式ドキュメントよりモジュールを読み込んだ時に発動するメソッドだと解ります。


つまり、include M とするとこのクラスメソッドが読み込み先のクラスで発動しbaseには読み込み先のクラスが入ってきます。

base.extend ClassMethods

読み込み先のクラスであるbaseClassMethodsというモジュールを拡張して、ClassMethodsに書いてあるメソッドをbaseがクラスメソッドとして使えるようになります。

base.class_eval do .. end

baseに中のインスタンスメソッドまたはクラスメソッドを追加しています。


ちなみに、scopeはクラスメソッドと同じように振る舞いますがifのような条件文を使う場合は注意が必要なようです。


参考: 公式ドキュメント


今回の記事は以上になります!読んでいただいてありがとうございます!


解りにくいところ、間違っているところなどあれば連絡いただければと思います。

連絡先

何か連絡をしたい際は以下 SNS、メールでお願いいたします。

Twitter:  https://twitter.com/naka_ryo_z

Github:  https://github.com/ryotaro-tenya0727

メール:   ryotaro123110@gmail.com

見出しへのリンク

© 2024, written by Nakayama

Powered by Gatsby