Ruby-on-rails inverse_of 有什么作用?它生成什么 SQL?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9296694/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What does inverse_of do? What SQL does it generate?
提问by Federico
I'm trying to get my head around inverse_ofand I do not get it.
我试图让我的头左右inverse_of,我不明白。
What does the generated sql look like, if any?
生成的 sql 是什么样的,如果有的话?
Does the inverse_ofoption exhibit the same behavior if used with :has_many, :belongs_to, and :has_many_and_belongs_to?
inverse_of如果与、 和一起使用:has_many,该选项是否表现出相同的行为?:belongs_to:has_many_and_belongs_to
Sorry if this is such a basic question.
对不起,如果这是一个如此基本的问题。
I saw this example:
我看到了这个例子:
class Player < ActiveRecord::Base
has_many :cards, :inverse_of => :player
end
class Card < ActiveRecord::Base
belongs_to :player, :inverse_of => :cards
end
采纳答案by tadman
From the documentation, it seems like the :inverse_ofoption is a method for avoiding SQL queries, not generating them. It's a hint to ActiveRecord to use already loaded data instead of fetching it again through a relationship.
从文档来看,该:inverse_of选项似乎是一种避免 SQL 查询的方法,而不是生成它们。它提示 ActiveRecord 使用已加载的数据,而不是通过关系再次获取它。
Their example:
他们的例子:
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
In this case, calling dungeon.traps.first.dungeonshould return the original dungeonobject instead of loading a new one as would be the case by default.
在这种情况下,调用dungeon.traps.first.dungeon应该返回原始dungeon对象,而不是像默认情况那样加载新对象。
回答by KenB
I think :inverse_ofis most useful when you are working with associations that have not yet been persisted. E.g.:
我认为:inverse_of在处理尚未持久化的关联时最有用。例如:
class Project < ActiveRecord::Base
has_many :tasks, :inverse_of=>:project
end
class Task < ActiveRecord::Base
belongs_to :project, :inverse_of=>:tasks
end
Now, in the console:
现在,在控制台中:
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, ...>
Without the :inverse_ofarguments, t.projectwould return nil, because it triggers an sql query and the data isn't stored yet. With the :inverse_ofarguments, the data is retrieved from memory.
没有:inverse_of参数,t.project将 return nil,因为它触发一个 sql 查询并且数据尚未存储。使用:inverse_of参数,从内存中检索数据。
回答by artamonovdev
After this pr (https://github.com/rails/rails/pull/9522) inverse_ofis not required in most cases.
在此 pr ( https://github.com/rails/rails/pull/9522)之后,在大多数情况下不需要inverse_of。
Active Record supports automatic identification for most associations with standard names. However, Active Record will not automatically identify bi-directional associations that contain a scope or any of the following options:
Active Record 支持自动识别大多数具有标准名称的关联。但是,Active Record 不会自动识别包含范围或以下任何选项的双向关联:
- :through
- :foreign_key
- :通过
- :foreign_key
class Author < ApplicationRecord
has_many :books, inverse_of: 'writer'
end
class Book < ApplicationRecord
belongs_to :writer, class_name: 'Author', foreign_key: 'author_id'
end
a = Author.first
b = a.books.first
a.first_name == b.writer.first_name # => true
a.first_name = 'David'
a.first_name == b.writer.first_name # => true
In the above example, a reference to the same object is stored in the variable aand in the attribute writer.
在上面的例子中,对同一个对象的引用存储在变量a和属性中writer。
回答by Gurudath BN
When we have 2 models with has_many and belongs_to relationship, it's always better to use inverse_of which inform ActiveRecod that they belongs to the same side of the association. So if a query from one side is triggered, it will cache and serve from cache if it get triggered from the opposite direction. Which improves in performance. From Rails 4.1, inverse_of will be set automatically, if we uses foreign_key or changes in class name we need to set explicitly.
当我们有 2 个具有 has_many 和belongs_to 关系的模型时,最好使用 inverse_of 来通知 ActiveRecod 它们属于关联的同一侧。因此,如果触发了来自一侧的查询,如果它是从相反方向触发的,它将缓存并从缓存中提供服务。这提高了性能。从 Rails 4.1 开始,inverse_of 将自动设置,如果我们使用外键或更改类名,我们需要显式设置。
Best article for details and example.
有关详细信息和示例的最佳文章。
http://viget.com/extend/exploring-the-inverse-of-option-on-rails-model-associations
http://viget.com/extend/exploring-the-inverse-of-option-on-rails-model-associations
回答by Richard Peck
Just an update for everyone - we just used inverse_ofwith one of our apps with a has_many :throughassociation
只是对每个人的更新 - 我们只是使用inverse_of了我们的一个has_many :through关联应用程序
It basically makes the "origin" object available to the "child" object
它基本上使“源”对象可用于“子”对象
So if you're using the Rails' example:
因此,如果您使用 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
Using :inverse_ofwill allow you to access the data object that it's the inverse of, without performing any further SQL queries
使用:inverse_of将允许您访问与其相反的数据对象,而无需执行任何进一步的 SQL 查询
回答by Informatom
If you have a has_many_throughrelation between two models, User and Role, and want to validate the connecting model Assignment against non existing or invalid entries with validates_presence of :user_id, :role_id, it is useful. You can still generate a User @user with his association @user.role(params[:role_id])so that saving the user would not result in a failing validation of the Assignment model.
如果您has_many_through在两个模型(用户和角色)之间存在关系,并且想要针对不存在或无效的条目验证连接模型分配validates_presence of :user_id, :role_id,则它很有用。您仍然可以使用他的关联生成一个 User @user,@user.role(params[:role_id])这样保存用户就不会导致 Assignment 模型验证失败。
回答by Samuel G. P.
Take a look at this article!!
看看这篇文章!!
http://gsusmonzon.blogspot.com.br/2011/09/rails-power-of-inverseof.html
http://gsusmonzon.blogspot.com.br/2011/09/rails-power-of-inverseof.html
回答by Leo Le
Please take a look 2 two useful resources
请看一下 2 两个有用的资源
- https://www.viget.com/articles/exploring-the-inverse-of-option-on-rails-model-associations
- http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#module-ActiveRecord::Associations::ClassMethods-label-Bi-directional+associations
- https://www.viget.com/articles/exploring-the-inverse-of-option-on-rails-model-associations
- http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#module-ActiveRecord::Associations::ClassMethods-label-Bi-directional+associations
And remember some limitations of inverse_of:
并记住一些限制inverse_of:
does not work with :through associations.
does not work with :polymorphic associations.
for belongs_to associations has_many inverse associations are ignored.
不适用于 :through 关联。
不适用于 :polymorphic 关联。
对于belongs_to 关联has_many 反向关联被忽略。

