2

私の現在のコード:

class Product < ActiveRecord::Base
  belongs_to :category
end

class Category < ActiveRecord::Base
  def method_missing name
    true
  end
end

Category.new.ex_undefined_method          #=> true
Product.last.category.ex_undefined_method #=> NoMethodError: undefined method `ex_undefined_method' for #<ActiveRecord::Associations::BelongsToAssociation:0xc4cd52c>

これは、モデルに存在するメソッドのみを渡すレール内のこのコードが原因で発生します。

private
def method_missing(method, *args)
  if load_target
    if @target.respond_to?(method)
      if block_given?
        @target.send(method, *args)  { |*block_args| yield(*block_args) }
      else
        @target.send(method, *args)
      end
    else
      super
    end
  end
end

これが私が欲しいものです:

Product.last.category.ex_undefined_method #=> true

どうすればこれを達成できますか?

4

3 に答える 3

8

AssociationProxyオブジェクトは、ターゲットが要求するメソッドのみを送信することに注意してくださいrespond_to?。したがって、ここでの修正はrespond_to?同様に更新することです。

class Category < ActiveRecord::Base
  def method_missing(name, *args, &block)
    if name =~ /^handleable/
      "Handled"
    else
      super
    end
  end

  def respond_to?(name)
    if name =~ /^handleable/
      true
    else
      super
    end
  end
end

実際、再定義する場合は常に更新する必要があります。クラスのインターフェースを変更したので、全員がそれを知っていることを確認する必要があります。ここを参照してください。respond_to?method_missing

于 2011-06-01T08:55:32.807 に答える
2

チャウレットの反応は確かに私見に行く方法です。

ただし、Rails 3 *を使用している場合は、responds_toに導入された2番目の引数を必ず含めてください。意味:

def respond_to?(name,include_private = false)
  if name =~ /^handleable/
    true
  else
    super 
  end
end
于 2011-09-22T13:13:19.177 に答える
0

交換

if @target.respond_to?(method)
  if block_given?
    @target.send(method, *args)  { |*block_args| yield(*block_args) }
  else
    @target.send(method, *args)
  end
else
  super
end

if block_given?
  @target.send(method, *args)  { |*block_args| yield(*block_args) }
else
  @target.send(method, *args)
end

AssociationProxyへのモンキーパッチとして

于 2011-06-01T08:52:44.397 に答える