Rails inverse_of不适用于条件

时间:2013-04-20 04:40:21

标签: ruby-on-rails database activerecord

以下是我的模特:

class Flight < ActiveRecord::Base
  has_many :seats, dependent: :destroy, inverse_of: :flight
end

class Seat < ActiveRecord::Base
  belongs_to :flight, inverse_of: :seats
end

似乎inverse_of效果很好,但是当我使用条件时它不起作用:

f1 = Flight.first
s1 = f1.seats.first
s2 = f1.seats.second
s3 = f1.seats.where(id: 0..1000000).third

s1.flight.equal? s2.flight
=> true
s1.flight.equal? s3.flight
=> false

这解释了什么?我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:0)

s1.flight.equal? s2.flight
=> true

以上结果为真,因为s1.flights2.flight引用完全相同的Ruby对象

s1.flight.equal? s3.flight

此处,s1.flights3.flight引用不同的Ruby对象。它们都包含相同的记录数据(包括相同的:id值)

当你应该使用Rails的==eql?比较器时,问题是你正在使用Ruby的equal?方法。

来自 the Ruby Object docs for == (aliased as eql? and equal?)

  

Equality - 在Object级别,只有当obj和other是同一个对象时,==才返回true。 通常,在子类中重写此方法以提供特定于类的含义。

不幸的是,equal?ActiveRecord::Base中覆盖的变种。来自 the Rails docs for == (aliased as eql?)

  

如果comparison_object是完全相同的对象,或者compare_object属于同一类型且self具有ID并且它等于comparison_object.id,则返回true。

你会发现这与:inverse_of无关。您可以尝试一个简单的例子

f1 = Flight.all.first
f2 = Flight.all.first

f1.eql? f2
=> true

f1 == f2
=> true

f1.equal? f2 # Direct Object comparison (skips ActiveRecord::Base)
=> false

答案 1 :(得分:0)

Inverse_of选项不适用于条件,这就是s1.flights3.flight不相等的原因 - ActiveRecord只是在您执行时从数据库重新加载对象{{ 1}}。这似乎是记录在案的行为,请参阅https://github.com/rails/rails/issues/23693#issuecomment-184438933