LoginSignup
6
1

More than 1 year has passed since last update.

extend Activesupport::Concernについて

Posted at

concernsに定義するモジュールでよく書かれているがいまいち何をしているのかよくわかっていなかったので調べました。

結論

単純に言えば、モジュールでのクラスメソッドの定義やそれをincludeする側でクラスメソッドとして追加する方法、クラスレベルでのメソッド呼び出しの容易な方法を提供してくれるものだと理解しました。

具体例

具体例は以下のページと同じものです。
https://api.rubyonrails.org/v6.1.4/classes/ActiveSupport/Concern.html

例えば、モジュールがincludeされたときに特定の処理を呼び出したり、モジュールのメソッドをクラスメソッドとして追加したい時、通常以下のように書きます。

module M
  # https://docs.ruby-lang.org/ja/latest/method/Module/i/included.html
  def self.included(mod)
    # includeする側(例えばクラス)の特異メソッドとしてClassMethodsを追加する -> クラスメソッドとして呼び出せる
    mod.extend ClassMethods
    mod.class_eval do
      before_action :xxx
    end
  end

  module ClassMethods
    # クラスメソッドを定義
  end
end

ActiveSupport::Concernを利用すると以下のように書けます。

module M
  extend ActiveSupport::Concern

  included do
    before_action :xxx
  end

  class_methods do
    # クラスメソッドを定義
  end
end

ActiveSupport::Concern内のicludedやclass_methodsなどのメソッドが面倒な記述を肩代わりしてくれ、簡潔に書けるようになります。
(extendしているのでMのクラスメソッドのように扱える)

  
また、モジュール間の依存関係もいい感じに整理して書けるようにしてくれます。

例えば以下の場合、HostクラスはBarモジュールをincludeしたいが、BarモジュールはFooモジュールに依存しているので、FooモジュールもHostがincludeしなければならない。

module Foo
  def self.included(base)
    base.class_eval do
      def self.method_injected_by_foo
        ...
      end
    end
  end
end

module Bar
  def self.included(base)
    base.method_injected_by_foo
  end
end

class Host
  include Foo # Hostが直接関係のないモジュールまでincludeしている
  include Bar
end

Barだけincludeしようとするとエラーになる。

class Host
  # include Foo
  include Bar
end

==>  undefined method `method_injected_by_foo' for Host:Class (NoMethodError)

ActiveSupport::Concernを使うと依存関係の記述を綺麗に整理できます。

module Foo
  extend ActiveSupport::Concern
  included do
    def self.method_injected_by_foo
      ...
    end
  end
end

module Bar
  extend ActiveSupport::Concern
  include Foo

  included do
    self.method_injected_by_foo
  end
end

class Host
  include Bar
end

参考

ActiveSupport::Concernが具体的に提供してくれるもの。(ソースコード)
https://github.com/rails/rails/blob/83217025a171593547d1268651b446d3533e2019/activesupport/lib/active_support/concern.rb#L110

6
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1