As of Rails 5, :inverse_of 什么时候需要手动设置?
As of Rails 5, when is :inverse_of necessary to set manually?
我在不同的地方读到它在某些情况下会自动推断出来,但我发现有关此功能的文档很难理解。任何人都可以阐明这些原则吗? 具体什么时候Rails可以反推,什么时候Rails不能反推?
我愿意考虑
- 多态关联
- 单一 tabled 继承(例如
BundleProduct
和 IndividualProduct
都继承自 Product
并使用 products
table)
- 常规 has_one/has_many/belongs_to 协会
- 有很多通过:协会
一些上下文: 我正在维护一个相当大的 9 岁 Rails 应用程序,其中有很多很多 table。我想就哪些模型需要添加 inverse_of:
而不是必须更改系统中的每个模型提供一些指导。
具体的推导过程可以在ActiveRecord::Reflection::AssociationReflection#automatic_inverse_of中查找。
Rails 尝试检测没有 through
、foreign_key
选项和范围的 has_many
、has_one
和 belongs_to
的逆并具有标准名称(这在 official guide 中也有描述)。
If you do not set the :inverse_of record, the association will do its
best to match itself up with the correct inverse. Automatic inverse
detection only works on has_many, has_one, and belongs_to
associations.
-- Rails API docs - ActiveRecord::Associations::ClassMethods
在您有 "non-standard" 命名的情况下,您可能需要提供以下选项:
The automatic guessing of the inverse association uses a heuristic
based on the name of the class, so it may not work for all
associations, especially the ones with non-standard names.
-- 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 or by using shoulda-matchers 与您的测试套件来手动测试是否需要它。
我在不同的地方读到它在某些情况下会自动推断出来,但我发现有关此功能的文档很难理解。任何人都可以阐明这些原则吗? 具体什么时候Rails可以反推,什么时候Rails不能反推?
我愿意考虑
- 多态关联
- 单一 tabled 继承(例如
BundleProduct
和IndividualProduct
都继承自Product
并使用products
table) - 常规 has_one/has_many/belongs_to 协会
- 有很多通过:协会
一些上下文: 我正在维护一个相当大的 9 岁 Rails 应用程序,其中有很多很多 table。我想就哪些模型需要添加 inverse_of:
而不是必须更改系统中的每个模型提供一些指导。
具体的推导过程可以在ActiveRecord::Reflection::AssociationReflection#automatic_inverse_of中查找。
Rails 尝试检测没有 through
、foreign_key
选项和范围的 has_many
、has_one
和 belongs_to
的逆并具有标准名称(这在 official guide 中也有描述)。
If you do not set the :inverse_of record, the association will do its best to match itself up with the correct inverse. Automatic inverse detection only works on has_many, has_one, and belongs_to associations.
-- Rails API docs - ActiveRecord::Associations::ClassMethods
在您有 "non-standard" 命名的情况下,您可能需要提供以下选项:
The automatic guessing of the inverse association uses a heuristic based on the name of the class, so it may not work for all associations, especially the ones with non-standard names. -- 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 or by using shoulda-matchers 与您的测试套件来手动测试是否需要它。