you*_*786 13 ruby-on-rails rails-activerecord
我有一个模型User,那个has_one :child和Child模型has_one :toy.
如果我有一个User类的单个实例,user我如何在一个查询中加载子和玩具?
这是不起作用的:
user.child.toy # 2 queries
user.includes(child: :toy) # can't call includes on a single record
user.child.includes(:toy) # same as above
user.association(:child).scope.eager_load(:toy).first # makes the appropriate query with both child and toy... but doesn't set the object on the user model.
user.child = user.association(:child).scope.eager_load(:toy).first # makes the appropriate query, but also calls another query before setting the child :(
Run Code Online (Sandbox Code Playgroud)
有没有办法做到这一点,不涉及重新查询用户模型.即.我想避免这种情况
User.where(id: user.id).eager_load(child: :toy).first
Run Code Online (Sandbox Code Playgroud)
Relavant模型声明:
class User < ActiveRecord::Base
has_one :child
has_one :toy, through: :child
end
class Child < ActiveRecord::Base
has_one :toy
belongs_to :user
end
class Toy < ActiveRecord::Base
belongs_to :child
end
Run Code Online (Sandbox Code Playgroud)
这有效,但并不理想.我认为我不应仅仅因为这个原因宣布另一种关系.
class User < ActiveRecord::Base
has_one :child
has_one :toy, through: :child
has_one :child_with_toy, ->{ eager_loads(:toy) }, class_name: "Child", foreign_key: :parent_id
end
Run Code Online (Sandbox Code Playgroud)
这允许我调用user.child_with_toy获取Child对象,并user.child_with_toy.toy获取Toy对象,同时只触发一个SQL查询.
Nat*_*han 10
如果您希望为已经实例化的记录急切加载单个关联的关联,则可以执行以下操作:
user.association(:child).target = user.association(:child).scope.eager_load(:toy).first
Run Code Online (Sandbox Code Playgroud)
这类似于您在问题顶部列出的方法之一.特别注意这.target部分.
ActiveRecord没有针对此特定方案进行优化,因此代码非常难看.因此,:child_with_toy如果您确实需要保存查询,我会强烈倾向于您的方法.
可以通过以下方法更轻松地完成Preloader:
ActiveRecord::Associations::Preloader.new.preload(user, child: [:toy])
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
472 次 |
| 最近记录: |