【问题标题】:Why are associated objects through a belongs_to not equal to themselves?为什么通过belongs_to关联的对象不等于自己?
【发布时间】:2009-09-25 08:06:06
【问题描述】:

我有两个具有 has_many 和 belongs_to 关联的类:

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

我希望 Contract 类的#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 中的错误吗?

感谢您的帮助。

【问题讨论】:

    标签: ruby-on-rails activerecord


    【解决方案1】:

    这与对象相等有关。考虑这个 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_id 不同,因此它们是否具有所有相同的值并不重要, == 将返回 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 方法(或者,如果我们正在比较的对象没有 id 方法,则只返回 false )。如果你想像这样按值比较员工,你必须定义自己的 == 方法来实现它。

    【讨论】:

    • 抱歉,您的回答没有抓住我想说的重点。我不想执行相等测试来检查两个对象是否相同。我只是想了解为什么通过 belongs_to 关联检索到的对象不等于自身。这怎么可能?我希望对于任何对象 x,x.equal?(x) 为真,但显然对于通过 belongs_to 关联检索的对象,x.equal?(x) 为假。
    【解决方案2】:

    这可能是因为 Rails 内部缓存在两个关联调用中不同。试着去做

      a.reload.equal? a.reload 
    

    这将摆脱缓存并应返回 true

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-30
      • 1970-01-01
      • 1970-01-01
      • 2012-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多