我写了一个方便的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>
任何人都可以告诉我为什么一个有效,另一个没有?
答案 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 永远不会被调用。