Fed*_*ico 133 activerecord ruby-on-rails
我正试图让我的头脑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
Run Code Online (Sandbox Code Playgroud)
tad*_*man 117
从文档中看,该: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
Run Code Online (Sandbox Code Playgroud)
在这种情况下,调用dungeon.traps.first.dungeon应返回原始dungeon对象,而不是默认情况下加载新对象.
Ken*_*enB 38
:inverse_of当您使用尚未持久化的关联时,我认为最有用.例如:
class Project < ActiveRecord::Base
has_many :tasks, :inverse_of=>:project
end
class Task < ActiveRecord::Base
belongs_to :project, :inverse_of=>:tasks
end
Run Code Online (Sandbox Code Playgroud)
现在,在控制台中:
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, ...>
Run Code Online (Sandbox Code Playgroud)
如果没有:inverse_of参数,t.project则会返回nil,因为它会触发sql查询并且数据尚未存储.使用:inverse_of参数,可以从内存中检索数据.
art*_*dev 13
从Rails 5.0的文档和伟大的.
双向关联
协会在两个方向工作是正常的,需要在两个不同的模型上进行声明:
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
Run Code Online (Sandbox Code Playgroud)
默认情况下,Active Record不知道这些关联之间的连接.这可能导致对象的两个副本不同步:
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
Run Code Online (Sandbox Code Playgroud)
发生这种情况是因为a和b.author是相同数据的两个不同的内存中表示,并且两个都不会自动从另一个的更改中刷新.Active Record提供:inverse_of选项,以便您可以告知它们这些关系:
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
Run Code Online (Sandbox Code Playgroud)
通过这些更改,Active Record将仅加载作者对象的一个副本,从而防止出现不一致并使您的应用程序更有效:
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
Run Code Online (Sandbox Code Playgroud)
inverse_of支持有一些限制:
它们不适用于:通过协会.它们不兼容:多态关联.它们不适用于:作为协会.
对于belongs_to关联,忽略has_many反向关联.每个关联都将尝试自动查找反向关联,并启发式地设置:inverse_of选项(基于关联名称).将支持大多数与标准名称的关联.但是,包含以下选项的关联不会自动设置其反转:
只是每个人的更新 - 我们只使用我们的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
Run Code Online (Sandbox Code Playgroud)
使用:inverse_of将允许您访问与其相反的数据对象,而不执行任何进一步的SQL查询
当我们有 2 个具有 has_many 和belongs_to 关系的模型时,最好使用 inverse_of 来通知 ActiveRecod 它们属于关联的同一侧。因此,如果触发了来自一侧的查询,如果它是从相反方向触发的,它将缓存并从缓存中提供服务。这提高了性能。从 Rails 4.1 开始,inverse_of 将自动设置,如果我们使用外键或更改类名,我们需要显式设置。
有关详细信息和示例的最佳文章。
http://viget.com/extend/exploring-the-inverse-of-option-on-rails-model-associations
| 归档时间: |
|
| 查看次数: |
40319 次 |
| 最近记录: |