我正试图绕过inverse_of
并且我没有得到它。
生成的sql是什么样的,如果有的话?
如果与inverse_of
,:has_many
和:belongs_to
一起使用,:has_many_and_belongs_to
选项是否会表现出相同的行为?
很抱歉,如果这是一个基本问题。
我看到了这个例子:
class Player < ActiveRecord::Base
has_many :cards, :inverse_of => :player
end
class Card < ActiveRecord::Base
belongs_to :player, :inverse_of => :cards
end
答案 0 :(得分:110)
从the documentation开始,似乎:inverse_of
选项是一种避免SQL查询而不是生成它们的方法。这是ActiveRecord使用已经加载的数据而不是通过关系再次获取数据的提示。
他们的例子:
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.traps.first.dungeon
应返回原始dungeon
对象,而不是默认情况下加载新对象。
答案 1 :(得分:37)
我认为:inverse_of
在您使用尚未保留的关联时最有用。 E.g:
class Project < ActiveRecord::Base
has_many :tasks, :inverse_of=>:project
end
class Task < ActiveRecord::Base
belongs_to :project, :inverse_of=>:tasks
end
现在,在控制台中:
irb> p = Project.new
=> #<Project id: nil, name: nil, ...>
irb> t = p.tasks.build
=> #<Task id: nil, project_id: nil, ...>
irb> t.project
=> #<Project id: nil, name: nil, ...>
如果没有:inverse_of
个参数,t.project
将返回nil
,因为它会触发sql查询并且数据尚未存储。使用:inverse_of
参数,可以从内存中检索数据。
答案 2 :(得分:12)
从Rails 5.0的文档和伟大的。
双向关联
协会在两个方向上工作是正常的,需要在两个不同的模型上声明:
class Author < ApplicationRecord
has_many :books
end
class Book < ApplicationRecord
belongs_to :author
end
默认情况下,Active Record不知道这些关联之间的连接。这可能导致对象的两个副本不同步:
a = Author.first
b = a.books.first
a.first_name == b.author.first_name # => true
a.first_name = 'Manny'
a.first_name == b.author.first_name # => false
这是因为a和b.author是相同数据的两个不同的内存中表示,并且没有一个会自动从另一个的更改中刷新。 Active Record提供:inverse_of选项,以便您可以告知它们这些关系:
class Author < ApplicationRecord
has_many :books, inverse_of: :author
end
class Book < ApplicationRecord
belongs_to :author, inverse_of: :books
end
通过这些更改,Active Record将只加载一个作者对象副本,防止出现不一致并提高应用程序效率:
a = Author.first
b = a.books.first
a.first_name == b.author.first_name # => true
a.first_name = 'Manny'
a.first_name == b.author.first_name # => true
inverse_of支持有一些限制:
它们不适用于:通过关联。 它们不兼容:多态关联。 它们不适用于:作为协会。
对于belongs_to关联,忽略has_many反向关联。 每个关联都将尝试自动查找反向关联,并启发式地设置:inverse_of选项(基于关联名称)。将支持大多数与标准名称的关联。但是,包含以下选项的关联不会自动设置其反转:
答案 3 :(得分:5)
只是每个人的更新 - 我们只使用了inverse_of
我们的某个应用与has_many :through
关联
它基本上使“原始”对象可用于“子”对象
所以,如果你使用Rails的例子:
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
validates :id,
:presence => { :message => "Dungeon ID Required", :unless => :draft? }
private
def draft?
self.dungeon.draft
end
end
class EvilWizard < ActiveRecord::Base
belongs_to :dungeon, :inverse_of => :evil_wizard
end
使用:inverse_of
将允许您访问与其相反的数据对象,而不执行任何进一步的SQL查询
答案 4 :(得分:4)
当我们有2个具有has_many和belongs_to关系的模型时,最好使用inverse_of来告知ActiveRecod它们属于关联的同一侧。因此,如果从一侧触发查询,如果从相反方向触发,它将从缓存缓存并提供服务。这提高了性能。从Rails 4.1开始,inverse_of将自动设置,如果我们使用foreign_key或我们需要明确设置的类名更改。
有关详细信息和示例的最佳文章。
http://viget.com/extend/exploring-the-inverse-of-option-on-rails-model-associations
答案 5 :(得分:3)
如果您在两个模型(用户和角色)之间存在has_many_through
关系,并希望使用validates_presence of :user_id, :role_id
针对不存在或无效的条目验证连接模型分配,则它非常有用。您仍然可以使用其关联@user.role(params[:role_id])
生成User @user,以便保存用户不会导致Assignment模型的验证失败。
答案 6 :(得分:3)
答案 7 :(得分:-1)
请查看2两个有用的资源
请记住inverse_of
的一些限制:
不适用于:通过关联。
不适用于:多态关联。
对于belongs_to关联,忽略has_many反向关联。