我认为这个查询错了吗?

时间:2015-01-14 10:10:07

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

我的关联(简化):

项目

has_many :users
has_many :tasklists

任务列表

has_many :tasks

任务

belongs_to :tasklist

用户

has_many :assigned_tasks, class_name: 'Task', foreign_key: 'assignee_id'

我想做什么

我想展示一个包含项目用户的项目资源,每个用户都包含他们分配的任务。

我试过了:

project = Project.includes(users: :assigned_tasks).find(params[:id])

这种工作除了它甚至返回不属于父项目的assigned_tasks。这不是我想要的。我只想要分配的任务是这个项目的孩子。

也许整个方法都不对。也许我应该首先考虑任务,例如:

project = Project.includes(tasklists: :tasks)

但接下来我将如何组织用户的任务?

我希望我在这里有意义。任何帮助将非常感激。 感谢

1 个答案:

答案 0 :(得分:2)

根据您的优先级,有多种方法可以解决此问题。让我们从查看您的第一个查询开始:

project = Project.includes(users: :assigned_tasks).find(params[:id])

这样做的好处是,您只执行一个数据库查询,可以回收所有信息 - 而且还有一个缺点就是您已经所有分配的任务,而不仅仅是这些任务。项目。但是,您可以随时在显示任务时过滤这些任务:

project.users.each do |user|
  user.assigned_tasks.select {|t| t.project_id == project.id}.each do |task|
    puts task
  end
end

或者,您可以首先检索项目及其用户:

project = Project.includes(:users).find(params[:id])

add a scope Task class Task < ActiveRecord::Base belongs_to :tasklist scope :for_project, -> (project) {joins(:tasklist).where(tasklist: {project: project})} end a where clause on the join只找到该项目的任务:

project.users.each do |user|
  user.assigned_tasks.for_project(project).each do |task|
    puts task
  end
end

然后您可以在显示任务时使用此范围:

project

这样做的缺点是你很可能遇到N+1 queries problem。这也不是清晰度的重大进步。


也许最好的方法是允许从class Project < ActiveRecord::Base has_many :users has_many :tasklists has_many :tasks, through: :tasklists end class Task < ActiveRecord::Base belongs_to :tasklist has_one :project, through: :tasklist end 对象直接访问项目的任务:

project.tasks

允许您通过project.tasks.group_by(&:user).each do |user, tasks] puts user.name tasks.each do |t| puts t end end 访问项目的任务。关联是Enumerable,因此您可以像使用任何数组一样使用group_by

project = Project.includes(:users, :tasks).find(params[:id])

为了减少数据库查询的数量,您可以使用项目加载任务:

{{1}}