method_missing覆盖不起作用

时间:2010-08-02 09:41:22

标签: ruby-on-rails ruby activerecord

我写了一个方便的ActiveRecord扩展来将方法委托给基础对象(基于multi-table inheritance

class ActiveRecord::Base
  def self.acts_as(base)
    class_eval %Q{
      def method_missing(method, *args, &blk)
        #{base}.send(method, *args, &blk)
      rescue NoMethodError
        super
      end
    }
  end
end

我有类和基地

# state class
class MyState < ActiveRecord::Base
  belongs_to :my_object
  acts_as :my_object
end

# base class
class MyObject < ActiveRecord::Base
  has_one :head, :class_name => 'MyState'
  has_one :tail, :class_name => 'MyState'
end

当我尝试这个时,我发现它在某些情况下不起作用。更具体地说,

> MyState.first.some_method_in_base
nil
> MyObject.first.tail.some_method_in_base
NoMethodError: undefined method `some_method_in_base' for #<ActiveRecord::Associations::HasOneAssociation:0xABCDEFG>

任何人都可以告诉我为什么一个有效,另一个没有?

1 个答案:

答案 0 :(得分:5)

运行MyObject.first.tail时,实际响应的对象是AssociationProxy

  

删除了大部分基本实例方法,并委托了       #notget来自@target的未知方法   method_missing的

您可以获得有关代理运行的更多详细信息:

MyObject.first.proxy_owner
MyObject.first.proxy_reflection
MyObject.first.proxy_target

如果您查看代码,只有当 MyState 响应 some_method_in_base 。 >正如您在下面的代码中看到的那样。

  private
    # Forwards any missing method call to the \target.
    def method_missing(method, *args, &block)
      if load_target
        if @target.respond_to?(method)
          @target.send(method, *args, &block)
        else
          super
        end
      end
    end

因此,您在目标类中定义的 method_missing 永远不会被调用。