2009-09-23 60 views
1

我有兩個類用的has_many和belongs_to的關聯:爲什麼通過belongs_to關聯的對象不等於自己?

class Employee < ActiveRecord::Base 
    has_many :contracts 
end 
class Contract < ActiveRecord::Base 
    belongs_to :employee 
end 

我期望由合同類的#employee方法返回的僱員將等於本身,這意味着下面的單元測試將通過。

class EmployeeTest < ActiveSupport::TestCase 
    test "an object retrieved via a belongs_to association should be equal to itself" do 
    e = Employee.new 
    e.contracts << Contract.new 
    assert e.save 
    a = e.contracts[0].employee 
    assert a.equal? a 
    end 
end 

但是,它失敗。我不明白。這是ActiveRecord中的錯誤嗎?

感謝您的幫助。

回答

3

這與對象相等有關。考慮此IRB會話

irb(main):010:0> Foo = Class.new 
=> Foo 
irb(main):011:0> f = Foo.new 
=> #<Foo:0x16c128> 
irb(main):012:0> b = Foo.new 
=> #<Foo:0x1866a8> 
irb(main):013:0> f == b 
=> false 

默認情況下,==會測試兩個對象具有相同的類型和相同的object_id。在activerecord中,它爲第一名員工提供數據庫,並通過參考方法再次爲員工提交數據庫,但這些是兩個不同的對象。由於object_ids不同,它們具有所有相同的值並不重要,==將返回false。要改變這種行爲,認爲這是第二屆IRB

irb(main):050:0> class Bar 
irb(main):051:1> attr_accessor :id 
irb(main):052:1> def ==(compare) 
irb(main):053:2> compare.respond_to?(:id) && @id == compare.id 
irb(main):054:2> end 
irb(main):055:1> end 
=> nil 
irb(main):056:0> a = Bar.new 
=> #<Bar:0x45c8b50> 
irb(main):057:0> b = Bar.new 
=> #<Bar:0x45c2430> 
irb(main):058:0> a.id = 1 
=> 1 
irb(main):059:0> b.id = 1 
=> 1 
irb(main):060:0> a == b 
=> true 
irb(main):061:0> a.id = 2 
=> 2 
irb(main):062:0> a == b 
=> false 

我在這裏所定義的==操作符來比較兩個對象的.ID方法(或只是返回false,如果我們是在比較對象不具有一個id方法)。如果你想通過像這樣的值比較員工,你必須定義你自己的==方法來實現它。

+0

很抱歉,但你的答案錯過我想拍點。我不想實施平等測試來檢查兩個對象是否相同。 我只想了解爲什麼通過belongs_to關聯檢索的對象不等於自身。這怎麼可能?我期望對於任何對象x,x.equal?(x)都是true,但顯然對於通過belongs_to關聯檢索的對象,x.equal?(x)爲false。 – 2009-09-24 06:43:36

0

這可能是因爲在兩個關聯調用中內部緩存區域不同。嘗試做

a.reload.equal? a.reload 

這將擺脫緩存,並且應該返回true

相關問題