Posted at

ActiveSupport::Concern と、Module#concerning

More than 5 years have passed since last update.

concern

関心事、関連、利害関係 など


Rails 4.0 -> concerns ディレクトリ

Mix-in 用のモジュールを置くディレクトリ concerns が定義された


  • app/models/concerns

  • app/controllers/concerns

それぞれ、モデル、コントローラーの Mix-in 用のモジュールを置く


何が得なの?


  • models や、controllersでしか使わない module は、concerns ディレクトリに置くというルールができた

  • lib になんでも置いちゃう病が少し良くなる

  • lib に色々置かれてて、何に使うコードなのかよくわからないのが色々あるという状況が少し良くなる

  • もしくは、勝手に独自のディレクトリに置かれるということが無くなった


ActiveSupport::Concern

Mix-in するモジュール側で、ActiveSupport の機能を使いたい場合は、

extend ActiveSupport::Concern を呼ぶこと


実装例


app/model/member.rb

class Member

include Human
end


app/model/concerns/human.rb

module Human

extend ActiveSupport::Concern

included do
attr_accessor :name
def self.default_name
"太郎"
end

def default_name?
name == self.class.default_name
end
end
end



実行結果

irb(main):001:0> m = Member.new

=> #<Member:0x007f92cfae15c8>
irb(main):002:0> m.name = "二郎"
=> "二郎"
irb(main):003:0> m.default_name?
=> false
irb(main):004:0> m.name = "太郎"
=> "太郎"
irb(main):005:0> m.default_name?
=> true

と、まぁこんな感じで、複数の model で使いたい機能を module 化したい時に、手軽に扱う事ができる


Rails 4.1 -> Module#concerning

Rails 4.1 では新たに Module#concerning が追加された

これは、Concern を 1つのファイル内でやりたいときに使えるっぽいのだが...?


実装例


app/model/member.rb

class Member

include Human
end

class Member
concerning :Human do
included do
attr_accessor :name
def self.default_name
"太郎"
end

def default_name?
name == self.class.default_name
end
end
end
end


こんな風に、concern ディレクトリをつかわずに、concerning ができる


使い道は?

多分だけど、1つのクラスの中で意味合いが異なる処理がある場合に、それを分割することで、感心事を分ける為の仕組みの様子

当然ながら複数のクラスで同一の処理を行ないたい場合は、4.0 の concerns ディレクトリの仕組みを使うべき


参考