1. ホーム
  2. ruby-on-rails

[解決済み] Rails 4で懸念事項を使用する方法

2022-03-15 10:42:39

質問

Rails 4のデフォルトのプロジェクトジェネレータでは、コントローラとモデルの下に"consitutions"というディレクトリが作成されるようになっています。ルーティングの懸念事項の使用方法についてはいくつか説明がありましたが、コントローラやモデルについては何も書かれていません。

現在のDCIのトレンドと関係があるのは間違いないと思いますので、試してみたいと思います。

問題は、この機能をどのように使用すればよいかということです。この機能を動作させるために、ネーミングやクラス階層をどのように定義すればよいかという規約があるのでしょうか?また、モデルやコントローラの中にどのように懸念を含めることができるでしょうか?

どのように解決するのですか?

そこで、自分で調べてみました。実は、とてもシンプルで強力なコンセプトなのです。それは、以下の例のように、コードの再利用に関係しています。基本的に、このアイデアは、モデルをクリーンアップするために、コードの共通および/またはコンテキスト固有のチャンクを抽出し、それらがあまりにも太く、乱雑になるのを避けることである。

例として、よく知られたパターンのひとつであるタグ付け可能なパターンを紹介しよう。

# app/models/product.rb
class Product
  include Taggable

  ...
end

# app/models/concerns/taggable.rb
# notice that the file name has to match the module name 
# (applying Rails conventions for autoloading)
module Taggable
  extend ActiveSupport::Concern

  included do
    has_many :taggings, as: :taggable
    has_many :tags, through: :taggings

    class_attribute :tag_limit
  end

  def tags_string
    tags.map(&:name).join(', ')
  end

  def tags_string=(tag_string)
    tag_names = tag_string.to_s.split(', ')

    tag_names.each do |tag_name|
      tags.build(name: tag_name)
    end
  end

  # methods defined here are going to extend the class, not the instance of it
  module ClassMethods

    def tag_limit(value)
      self.tag_limit_value = value
    end

  end

end

つまり、Productのサンプルに倣って、任意のクラスにTaggableを追加し、その機能を共有することができるのです。

これは、かなりよく説明されている DHH :

Rails 4では、プログラマが懸念事項を使用するために デフォルトの app/models/concerns と app/controllers/concerns ディレクトリー これは自動的にロードパスの一部となります。また ActiveSupport::Concernラッパーは、この 軽量なファクタリング機構が輝きます。