如何使用has_many通过关系缩短三重连接ActiveRecord查询?

时间:2017-12-19 21:56:36

标签: mysql ruby-on-rails ruby ruby-on-rails-3 activerecord

我正在尝试清理一个很长的ActiveRecord查询。我拥有的那个正在工作,虽然看着它会很痛。这是正在发生的事情。

1)User has_many SimulationsUserSimulations(反之亦然)。

2)User has_many GroupsUserGroups(反之亦然)。

3)Group has_many SimulationsSimulationGroups(反之亦然)。

最终发生的事情是,用户可以通过两种方式与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 对象。

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

我很高兴它正在运行但想要清理它以便更简洁(不是4行代码来构建单个查询)。

更新

以下是涉及的模型。

Simulation.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

Group.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

User.rb

    & 'c:\program files\7-zip\7z.exe' a "$file1.zip" $file1 -p123

1 个答案:

答案 0 :(得分:0)

这个怎么样?

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))"