如何使用has_many通过关系缩短三重连接ActiveRecord查询?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用has_many通过关系缩短三重连接ActiveRecord查询?相关的知识,希望对你有一定的参考价值。
我正在尝试清理一个很长的ActiveRecord
查询。我拥有的那个正在工作,虽然看着它会很痛。这是正在发生的事情。
1)User
has_many Simulations
通过UserSimulations
(反之亦然)。
2)User
has_many Groups
通过UserGroups
(反之亦然)。
3)Group
has_many Simulations
通过SimulationGroups
(反之亦然)。
最终发生的是用户可以通过两种方式与Simulation
相关联,可以直接通过has_many与has_many关系,也可以通过用户所属的Group
间接关联。
我已经能够在一个查询中收集用户可以访问的所有Simulations
,它看起来像这样。我可以访问需要调用查询的current_user
对象。
# Define Queries
user_sim_join = "LEFT JOIN user_simulations ON user_simulations.simulation_id = simulations.id"
user_grp_join = "LEFT JOIN user_groups ON user_groups.group_id = groups.id"
where_clause = ["user_groups.user_id = :user_id OR user_simulations.user_id = :user_id", { user_id: user.id }]
# Run Query
Simulation.joins(user_sim_join, :groups, user_grp_join).where(where_clause).group('simulations.id')
#=> Simulation Load (1.1ms) SELECT "simulations".* FROM "simulations"
INNER JOIN "simulation_groups" ON "simulation_groups"."simulation_id" = "simulations"."id"
INNER JOIN "groups" ON "groups"."id" = "simulation_groups"."group_id"
LEFT JOIN user_simulations ON user_simulations.simulation_id = simulations.id
LEFT JOIN user_groups ON user_groups.group_id = groups.id
WHERE (user_groups.user_id = 2 OR user_simulations.user_id = 2)
GROUP BY simulations.id
我很高兴它正在工作但是想要清理它以便更简洁(不是4行代码来构建单个查询)。
UPDATE
以下是涉及的模型。
Simulation.rb
class Simulation < ApplicationRecord
# Associations
belongs_to :company
has_many :simulation_groups
has_many :user_simulations
has_many :objection_responses
has_many :groups, through: :simulation_groups
has_many :users, through: :user_simulations
has_many :reports, as: :reportable
has_many :objections, as: :objectionable
# Validations
end
Group.rb
class Group < ApplicationRecord
belongs_to :company
has_many :simulation_groups
has_many :simulations, through: :simulation_groups
has_many :user_groups
has_many :users, through: :user_groups
has_many :minigame_groups
has_many :minigames, through: :minigame_groups
has_many :reports, through: :users
# Validations
end
User.rb
class User < ApplicationRecord
# Associations
belongs_to :company
has_one :avatar
has_many :reports
has_many :events
has_many :training_sessions
has_many :user_groups
has_many :groups, through: :user_groups
has_many :objection_responses
has_many :user_simulations
has_many :simulations, through: :user_simulations
has_many :minigame_users
has_many :minigames, through: :minigame_users
# Validations
end
那这个呢?
scope :from_user, lambda{|user|
joins('left join user_simulations us ON (us.simulation_id = simulations.id)').
joins('left join group_simulations gs ON (gs.simulation_id = simulations.id)').
where("us.user_id = ? OR gs.group_id IN (?)",
user.id,
UserGroup.select("group_id").where(user_id: user.id))}
Simulation.from_user(用户).to_sql:
"SELECT `simulations`.* FROM `simulations`
left join user_simulations us ON (us.simulation_id = simulations.id)
left join group_simulations gs ON (gs.simulation_id = simulations.id)
WHERE (us.user_id = 1 OR gs.group_id IN (
SELECT `user_groups`.`group_id` FROM `user_groups`
WHERE `user_groups`.`user_id` = 1))"
以上是关于如何使用has_many通过关系缩短三重连接ActiveRecord查询?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用带有 has_many 的 PaperTrail 版本控制:通过在 Rails 4 中实现关联
Kohana 3 ORM - 使用静态方法连接和 has_many 关系
有关如何使用has_many:through关系正确设置验证的指导?