从 Rails 5 开始,何时需要手动设置 :inverse_of?
Posted
技术标签:
【中文标题】从 Rails 5 开始,何时需要手动设置 :inverse_of?【英文标题】:As of Rails 5, when is :inverse_of necessary to set manually? 【发布时间】:2019-01-09 09:15:34 【问题描述】:我在不同的地方读到它在某些情况下会自动推断,但我发现有关此功能的文档很难理解。任何人都可以阐明这些原则吗? Rails 什么时候能够推断,Rails 什么时候不能推断逆?
我想考虑
多态关联 单表继承(例如,BundleProduct
和 IndividualProduct
都继承自 Product
并使用 products
表)
常规 has_one/has_many/belongs_to 关联
有很多通过:关联
一些背景:我正在维护一个相当大的 9 年历史的 Rails 应用程序,其中包含很多很多表。我想要一些关于哪些模型需要添加inverse_of:
而不必更改系统中的每个模型的指导。
【问题讨论】:
请检查这里(也许你已经这样做了,无论如何..):guides.rubyonrails.org/…,确切地说:“通过在 has_many 关联声明中包含:inverse_of option
,Active Record 现在将识别双向协会:...”。还有guides.rubyonrails.org/…、guides.rubyonrails.org/…。或者你可以举个例子来缩小你的问题范围。
我在问题中添加了更多上下文,以便您了解我的困境。
【参考方案1】:
如果你不设置 :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 来手动测试是否需要。
【讨论】:
【参考方案2】:您可以在ActiveRecord::Reflection::AssociationReflection#automatic_inverse_of 中查找确切的推断过程。
Rails 尝试检测不具有 through
、foreign_key
选项和范围且具有标准名称的 has_many
、has_one
和 belongs_to
的逆向(这也在 official guide 中进行了描述)。
【讨论】:
以上是关于从 Rails 5 开始,何时需要手动设置 :inverse_of?的主要内容,如果未能解决你的问题,请参考以下文章
Rails 如何知道何时从 `sessions` 表中删除记录?
502 Bad Gateway (too big header) on Elastic Beanstalk Nginx with Rails 5 App in Production