>Models
用户有客户,客户有有任务的项目。
我正在尝试构建一个带有 [名称、计数] 的数组以发送到 Google 图表 - 除了一个之外,我已经解决了所有这些问题:
def task_by_project(user)
task_arr = user.projects.joins(:tasks).where("tasks.completed = ?", "0").uniq.collect { |d| [d.name, d.tasks.count] }.to_a
task_arr.unshift(['Projects', 'Uncompleted Tasks'])
return task_arr
end
此查询返回 11 个条目。这实际上是该用户的所有条目。它完全绕过了where
。有7个未完成的4个已完成。
在视图中,我用循环渲染它略有不同:
<% current_user.projects.uniq.each do |project| %>
<%= link_to project.name + " || " + project.tasks.where(completed: 0).count.to_s + " tasks remaining currently", project, :class => "collection-item" %>
<% end %>
</div>
我相当有信心这与我对如何查询如此深刻的关联的误解有关。
最终结果是我需要项目的名称,以及它有多少任务。
我通过查询将Task
连接回Project.ID
Project
来做到这一点 - 但我不确定如何处理整个集合。
("取消移位"的目的是因为从其他方面来看,我最终得到的结果格式是[[['Projects', 'Tasks'], [['First Record, 2] ... ]]
而不是 GCharts 格式。更平坦的杀了它 - 太多 - )
也许是这样的?
projects = user.projects
.select("projects.name, COUNT(uncompleted_tasks.id) AS uncompleted_tasks_count")
.joins("LEFT OUTER JOIN tasks AS uncompleted_tasks ON uncompleted_tasks.project_id = projects.id AND uncompleted_tasks.completed = 0")
.group("projects.id")
.map { |project| [project.name, project.uncompleted_tasks_count] }
改用 .pluck
获取列值
user.projects.left_joins(:tasks).where("tasks.completed = 0")
.distinct
.pluck('users.id, users.name, tasks.count')
.map { |a| a.pop(2) }
.pluck
效率要高得多,因为它只是查询传递给 ppick 的列并返回数组数组,而不是将一堆模型加载到内存中。
# => [[1, 'Frank', 0], [2, 'Muhammad', 5], [3, 'Jane', 3]]
但是,除非您的名称列是唯一的,否则您应该选择用户 ID 以清除重复项。 .map { |a| a.pop(2) }
删除结果数组中的 id。
从数据库中提取记录并对其调用.uniq
是一个巨大的反模式。您正在从数据库中提取大量数据,然后在 Ruby 中整理重复项。这可能会导致严重的性能问题。
处理状态的更好方法是使用 ActiveRecord::Enum:
class Task
enum :status, [:incomplete, :complete, :deleted]
end
这将允许您查询:
Task.incomplete
Task.completed
并为您提供了交互和突变方法:
task.complete?
task.complete!
您可以像这样使用它:
user.projects.left_joins(:tasks).where(tasks: Task.incomplete)
.distinct
.pluck('users.id, users.name, tasks.count')
.map { |a| a.pop(2) }