has_many的不可靠行为:inverse_of选项

时间:2012-08-04 09:22:54

标签: ruby-on-rails activerecord

rails documentation获取示例:

class Dungeon < ActiveRecord::Base
  has_many :traps, :inverse_of => :dungeon
  has_one :evil_wizard, :inverse_of => :dungeon
end

class Trap < ActiveRecord::Base
  belongs_to :dungeon, :inverse_of => :traps
end

class EvilWizard < ActiveRecord::Base
  belongs_to :dungeon, :inverse_of => :evil_wizard
end

Dungeon.create!.traps.create!
d = Dungeon.first
t = d.traps.first
d.level == t.dungeon.level # => true
d.level = 10

以下表达式返回false,但预期返回true(至少对于Rails 3.1):

d.level == t.dungeon.level # => false

:inverse_of出了什么问题?

1 个答案:

答案 0 :(得分:0)

我不确定这是否是一个错误,但是当你使用关系这样的关联时,inverse_of不起作用:

d.traps.where('1=1')[0].dungeon.object_id != d.object_id
d.traps.first.dungeon.object_id != d.object_id

虽然当你像数组一样使用它时,inverse_of表现正常:

d.traps.map { |t| t.dungeon.object_id } == [d.object_id]
d.traps[0].dungeon.object_id == d.object_id

创建对象时它可以正常工作:

d.traps.build.dungeon.object_id == object_id

对于带有has_many的belongs_to(它在文档中的某处指定)它不起作用:

t.dungeon.tasks[0].object_id != t.object_id

所以要避免inverse_of

的惊喜
  1. 使用[0]代替first
  2. 不要实现依赖它的逻辑(其他人可能用[{1}}替换你的select(&:some_predicate?)而你的代码将不再有效)
  3. 请勿在关联的另一端使用some_scope inverse_ofbelongs_to