6

まず、Railsの懸念事項についてここで見つけたプラクティスに従っています(素晴らしいアイデアです!):https ://gist.github.com/1014971

ただし、エラーが発生します。

undefined method `search' for #<Class:0x5c25ea0>
app/controllers/accessories_controller.rb:6:in `index'

/app/models/concerns/ディレクトリを/config/application.rbにロードしていますしたがって、「懸念」モジュールがロードされています。それを指摘したかっただけです。

これが私のコードです:

/app/models/concerns/searchable.rb

module Searchable
  extend ActiveSupport::Concern

  # Add a "search" scope to the models
  def self.search (search)
    if search
      where('name LIKE ?', "%#{search}%")
    else
      scoped
    end
  end
end

/app/models/accessory.rb

class Accessory < ActiveRecord::Base
  include Searchable

  ...
end

/app/controllers/accessories_controller.rb

class AccessoriesController < ApplicationController

  def index
    @accessories  = Accessory.search(params[:search])

    ...
  end

end
4

3 に答える 3

9

さて、もう少しいじって、何が悪いのか理解しました!

モジュール内からモデルを直接変更する場合(懸念事項)、含まれているブロック内に機能をラップする必要があります。

懸念モジュールを次のように変更しました。

    module Searchable
        extend ActiveSupport::Concern

        included do
            # Add a "search" scope to the models
            def self.search (search)
                if search
                    where('name LIKE ?', "%#{search}%")
                else
                    scoped
                end
            end
        end

    end

それだ!うまくいけば、これは同じ質問を持つ他の誰かを助けるでしょう!

于 2012-07-17T01:34:10.333 に答える
8

それはまともな解決策ですが、実際には最良の解決策ではありません。モジュールを構築するときに、懸念事項の内部にActiveSupport::Concern呼び出されたモジュールをラップできClassMethodsます。懸念事項を含むモジュールは、ClassMethodsモジュールとともに自動的に拡張されます。

したがって、より良い解決策は次のようになります。

module Searchable
  extend ActiveSupport::Concern

  module ClassMethods
    def search(search)
      if search
        where('name LIKE ?', "%#{search}%")
      else
        scoped
      end
    end
  end
end

それ(IMO)は、クラスレベルのメソッドをクラスに配置するという意図をより明確に表現します。

アプローチは機能しincludedますが、呼び出し元のクラスでメソッドを呼び出す必要がある場合は、メソッドを使用する方が適切です。たとえば、以下に示すように、Searchableオブジェクトにdb-backedname属性があると主張することができます。このincludedメソッドは、呼び出し元のクラスにバリデーターを追加しておりpresence、クラスを拡張するために使用しているメソッドは明確に分離されています。

module Searchable
  extend ActiveSupport::Concern

  def self.included(base)
    base.send :validates_presence_of, :name
  end

  module ClassMethods
    def search(search)
      if search
        where('name LIKE ?', "%#{search}%")
      else
        scoped
      end
    end
  end
end
于 2013-04-12T13:58:32.550 に答える
2

AndyVが指摘しているように、正しい解決策は次のとおりです。

module Searchable
  extend ActiveSupport::Concern

  module ClassMethods
    def search(search)
      if search
        where('name LIKE ?', "%#{search}%")
      else
        scoped
      end
    end
  end
end

また、ソリューションで行っているようにブロックで定義self.searchしないincludedでください。これは、より冗長で明確ではありません。

しかし、私はAndyVの使用法に同意しませんself.included。を使用する場合ActiveSupport::Concern、それはブロックシンタックスシュガーを持っているincludedので、それを使用する必要があります。self.included呼び出すメソッドまたは定義するメソッドの順序が重要な場合にのみ依存します。

于 2013-05-04T21:29:52.187 に答える