りんごとバナナとエンジニア

エンジニア修行の記録

RailsのActiveSupport:Concernの役割

Railsで共通部分をmoduleに切り出し、Concernを使う機会があったが、そもそもRubyであまりmoduleを使ったことがなく、Concermが通常のmodule機能と比べてどう特殊なのかわからなかった。この機会におさらいしてみる。

Rubyのmoduleの使い方

まずはRails以前の、Rubyでのmoduleについて。moduleに定義した変数は、moduleの名前とともに指定すれば使うことができる。

mod Constant
    NUMBER = 5
end

class Hoge
    a = Constant::NUMBER # 5
end

しかし、メソッドはこのやり方では使えない。moduleで定義したメソッドを使うためには、includeをする必要がある。includeとは、そのmodule内で定義されたメソッドや変数を引き継ぐことであり、mix-inとして使うことができる。

mod Constant
    def plus_one(num)
        num + 1
    end
end

class Hoge
    include Constant
    a = plus_one(4) # 5
end

includeされたメソッドは、そのクラスのインスタンスメソッドとして使うことができる。

Concernでクラスメソッドを楽に使う

ただし、上記のincludeができるのはインスタンスメソッドのみであり、クラスメソッドをmoduleで定義して外から使うためには複雑な記法を使わなければならない。とはいえRailsの場合、データ取得の際などにクラスメソッドを使う機会が多い。
そこでConcernを使うことで、クラスメソッドをmodule化しやすくなる。

module M
  extend ActiveSupport::Concern

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

  class_methods do
    ...
  end
end

上記のscopeは当然クラスメソッドだが、 included do ... end の中に書くだけになっている。あとはこのmoduleを対象クラスにincludeすれば、そのクラス内で定義したscopeと同じように、 :disabled のスコープを使えるようになる。

Railsは様々な独自記法があると聞いていたが、こんな形であるとは知らなかった。Railsしか知らないとどれが独自の書き方がわからなさそうなので、Rubyの文法と比べる習慣をつけていきたい。