从Rails 5开始,何时需要手动设置:inverse_of?

时间:2019-01-09 09:15:35

标签: ruby-on-rails rails-activerecord

我在不同的地方都读到它在某些情况下会自动推断出来,但是我发现此功能的文档很难遵循。谁能阐明一些原则? 具体来说,Rails何时可以推断,Rails何时不能推断逆?

我想考虑

  • 多态关联
  • 单个表继承(例如BundleProductIndividualProduct都从Product继承并使用products表)
  • 常规has_one / has_many / belongs_to关联
  • 有很多通过:关联

某些情况:我正在维护一个具有许多表的相当大的9年历史的Rails应用程序。我想对哪些模型需要添加inverse_of:有所帮助,而不必更改系统中的每个模型。

2 个答案:

答案 0 :(得分:1)

inverse_of被广泛误解。之所以存在,是因为关联的对象默认情况下不指向相同的内存中对象。

  

如果您未设置:inverse_of记录,则关联将执行其   最好将自己与正确的逆匹配。自动逆   检测仅对has_many,has_one和belongs_to起作用   协会。
  -Rails API docs - ActiveRecord::Associations::ClassMethods

在使用“非标准”命名的情况下,您可能需要提供以下选项:

  

逆关联的自动猜测使用启发式   基于类的名称,因此它可能不适用于所有人   关联,尤其是具有非标准名称的关联。   -Rails API docs - ActiveRecord::Associations::ClassMethods

例如:

class Pet < ApplicationRecord
  belongs_to :owner, class_name: 'User'
end

class User < ApplicationRecord
  has_many :pets
end

如果我们调用pet.owner,即使我们已经加载了该记录,也可能导致数据库命中。

如果我们添加inverse_of选项:

class Pet < ApplicationRecord
  belongs_to :owner, class_name: 'User', inverse_of: :pets
end

class User < ApplicationRecord
  has_many :pets, inverse_of: :owner
end

现在,如果我们已经在内存中存储了owner条记录,那么pet.owner将指向相同的owner

通常,显式设置inverse_of并没有什么害处,因此可以在不确定的每种情况下进行设置。您还可以通过查看accessing the assocation creates a DB query via the console或在测试套件中使用shoulda-matchers来手动测试是否需要。

答案 1 :(得分:0)

您可以在ActiveRecord::Reflection::AssociationReflection#automatic_inverse_of中查找确切的推断过程。

Rails尝试为has_manyhas_onebelongs_to没有throughforeign_key选项和范围并且具有标准名称(这是official guide中也有介绍。)