こんにちは、鈴木です。
Rails 4.1.0 で Module#concerning というメソッドが追加されました。
Module#concerning とは
Rails 4.0 で concerns ディレクトリが追加されたことを覚えているでしょうか。(see 「2.4. concerns ディレクトリの導入」)
concerns ディレクトリに Mixin 用のモジュールを置いて、それをモデルなりコントローラなりで include する、という使い方をするものですが、Module#concerning を用いると、わざわざ concerns ディレクトリにファイルを作成せずに、モデルクラスの中に記述することができます。
コードで表すと、Rails 4.0 では以下のように書くことができるようになりました。
1 2 3 4 5 6 7 8 9 |
# app/models/article.rb class Article < ActiveRecord::Base include Tagging end # app/models/concerns/tagging.rb module Tagging ... end |
それが Rails 4.1.0 で追加される Module#concerning を使うと、次のように書くことができます。
1 2 3 4 5 6 |
# app/models/article.rb class Article < ActiveRecord::Base concerning :Tagging do ... end end |
複数のファイルに分散せずにスッキリ記述できるようになりました!・・・のでしょうか。
少し経緯を振り返ってみましょう。
「Fat Controller」から「Skinny Controller, Fat Model」へ
ビジネスロジックに関する処理など、本来の役割を超えたコードで肥大化したコントローラのことを「Fat Controller」と呼ぶことがあります。「Fat Controller」にはコードの見通しが悪く、テストもしづらいという問題があります。
「Fat Controller」にならないようにするために、役割を考えた上でコードを実装する場所を決める必要があります。例えばビジネスロジックであればコントローラではなくサービス層に記述するなどです。
ところが Rails では少し困ったことがあります。それは、デフォルトではサービス層が用意されていないということです。モデルは app/models/、View なら app/views/、コントローラなら app/controllers/ というディレクトリが用意されていますが、サービス層を置くためのディレクトリはありません。
それでどうなったかというと、lib/ ディレクトリにサービス層を作ってみたり、app/services のようなディレクトリを作ってみたり、もしくは Fat Controller になってしまったり、はたまた View に大量のロジックを書いてしまったり、人によってバラバラな対応がなされました。
そんな状況の中で「Skinny Controller, Fat Model」と言われるようになりました。View やコントローラに本来の役割とは違うコードを書くのではなくモデルにコードを寄せましょう、ということです。
Fat Model から関心事を分離する
「Skinny Controller, Fat Model」という指針によってモデルにコードが集まるようになりました。
Fat Model になったことで、今度はモデルの見通しが悪くなりました。色々なコードをモデルに寄せていったので、モデルの見通しが悪くなることは当たり前ではあります。
そこで Rails 4.0 では app/models/concerns や app/controllers/concerns というディレクトリが用意されるようになりました。Fat Model とは言っても、ある程度独立した機能や複数モデルで共通するコードはモジュールに分離して concerns ディレクトリにおきましょう、ということです。
そして Module#concerning
そして Rails 4.1.0 では冒頭で紹介した Module#concerning というメソッドが追加されました。
これはモジュールに分割したコードを app/models/concerns や app/controllers/concerns にファイルとして保存せずに、モデルやコントローラ内にそのコードを記述できるようにする機能です。
「はて、Fat Model に戻るのでは?」という疑問が沸いてきます。
今現在、Module#concerning の具体的な活用例は思いついていません。「この場合は concerns ディレクトリにファイルを作りましょう。こういう場合は Module#concerning を使いましょう。」と言えたら良いのですが・・・。
少なくとも「今後は concerns ディレクトリにファイルを作るのではなく Module#concerning を使いましょう。」と単純に扱って良いものではなく、微妙なバランス感覚を要求される新機能なのだと感じています。