Я пытаюсь очистить очень длинный запрос ActiveRecord
. У меня есть работа, хотя мне больно смотреть на нее. Вот что происходит.
1) User
has_many Simulations
через UserSimulations
(и наоборот).
2) User
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 строки кода для создания одного запроса).
Здесь представлены модели.
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))"