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

Jac*_*lla 6 ruby-on-rails rails-activerecord

我在很多地方都读到过,在某些情况下它会自动推断出来,但我发现有关此功能的文档很难理解。任何人都可以阐明一些原则吗?具体来说,Rails 什么时候可以推断,Rails 什么时候不能推断逆?

我想考虑

  • 多态关联
  • 单表继承(例如 whereBundleProductIndividualProductboth 继承Product和使用products表)
  • 常规 has_one/has_many/belongs_to 关联
  • 有很多通过:协会

一些上下文:我正在维护一个相当大的 9 年前的 Rails 应用程序,其中有很多很多表。我想就哪些模型需要添加inverse_of:而不是更改系统中的每个模型提供一些指导。

max*_*max 11

如果您不设置 :inverse_of 记录,关联将尽最大努力将自己与正确的逆进行匹配。自动逆向检测仅适用于 has_many、has_one 和belongs_to 关联。
-- Rails API 文档 - ActiveRecord::Associations::ClassMethods

但是,如果您有“非标准”命名,您可能需要提供以下选项:

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

例如:

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

class User < ApplicationRecord
  has_many :pets
end
Run Code Online (Sandbox Code Playgroud)

如果我们调用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
Run Code Online (Sandbox Code Playgroud)

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

通常,明确设置 没有任何害处,inverse_of因此您可以为不确定的每种情况设置它。您还可以通过查看访问关联是否通过控制台创建数据库查询或在测试套件中使用shoulda-matchers来手动测试是否需要。