2011-11-17 86 views
1

我遇到了has_one关联与Object方法覆盖相结合的一个奇怪的问题。有人可以向我解释发生了什么事吗?Rails的ActiveRecord has_one关联与对象方法覆盖

这是怎么一回事呢:

我有SupplierAccount之间的has_one关系,就像在Rails的指南中使用的has_one例子的例子。

供应商:

class Supplier < ActiveRecord::Base 

    validates :name, :presence => true 

    has_one :account 

    nilify_blanks 
end 

帐户:

class Account < ActiveRecord::Base 

    belongs_to :supplier 

    validates :supplier_id, :presence => true 

    nilify_blanks 

    def foo 
    puts 'in account' 
    end 

    def to_s 
    puts 'in account' 
    end 

end 

我也有Object的方法foo如下:

class Object 
    def foo 
    puts 'in object' 
    end 
end 

当我打电话:

Supplier#account#to_s 

我 '帐户' 获得

当我打电话:

Supplier#account#foo 

我得到 '的对象'

,而我希望它 '帐户'

打印有没有人有任何线索为什么会发生这种情况?这是Rails ActiveRecord中的错误吗?

在此先感谢

附:如果你愿意,你可以得到一个完全成熟的应用程序,从这里演示该问题:

https://github.com/pmatsinopoulos/test_association_and_object_method_override.git

+0

实际帐户对象? –

+0

@NarenSisodiya是的。它具有相同的行为。 –

回答

2

做一些调查为例跟我的一个朋友后,得到了这样assoiciation作品。

当我们做Supplier.account它会给你AssociationProxy的对象不是一个帐户的对象。 AssociationProxy将所有方法委托给关联的对象,如果它的定义本身不存在的话(它也委托像类,检查等方法,这样你就可以得到实际的类名)。 现在,当我们在Object类中添加foo时,它在AssociationProxy中可用,并且当您说Supplier.account时,它将从AssociationProxy调用foo,而不是从帐户中调用。

,如果你想调用的帐户使用目标foo方法你有帐户= Supplier.account和account.foo尝试得到像

Supplier.account.target.foo #=> foo from account 
+0

非常感谢您的回答。它解释了正在发生的事情。此外,你的“目标”方法的作品。你当然可以同意这是一个*解决方法*,并且要求我将在我所有的'has_one'关联和我调用的所有方法上使用'target',因为我无法事先知道哪些是我的目标模型方法也在'Object'上定义。因此,你的答案*答案*我的问题减半。在接受你的答案之前,我将等待一段时间,看看是否有回答我的问题,即这是否是Rails中的错误。 –

+0

问题仍然是关于'to_s'。为什么'to_s'是按预期调用的。 'to_s'已经存在于'Object'中,因此存在'AssociationProxy',不是吗? –

+1

to_s可以工作,因为AssociationProxy类在内存中加载时未定义所有实例方法。如果您在加载AssociationProxy之前覆盖对象,Supplier.account.foo也可以工作。我试过把对象覆盖代码放在顶部的enviroment.rb文件中,并让它工作。 –