我有三级关系。
用户has_many客户端has_many项目
User.projects
可以正常工作User.clients
。
在视图中,我试图让每个客户的项目分解,用户有。
IE客户端A有2个项目,客户B有4个,客户C有3个。它将返回"客户A:2。客户B:4。客户C 3。"
我现在最接近的是pie_chart current_user.projects.group(:client).count
,它实际上只是返回#<Client:0x000000xd3948>
的某些东西 - 我假设的模型/关系。
我尝试current_user.clients
,所有记录都会返回undefined
。
我想也许我需要将它移动到帮助器并迭代user.clients
并计算它,但考虑到这种关系,这似乎是错误的。
(不确定要添加的其他输入)
基本上我需要一个Group By
但是在Rails上挣扎。
SELECT clients.name, count(*) FROM clients JOIN projects on clients.id = projects.client_id WHERE user_id = 1 GROUP BY clients.name;
此查询返回我需要的确切结果。
答案 0 :(得分:0)
为了解决这个问题,我最终使用了ERB - &gt;我过去做过的JavaScript。
1)我创建了一个帮助器来生成数组。 Google Charts想要的格式是[Name,Count]
module ProjectsHelper
def get_projects_per_client(user)
custom_arr = []
custom_arr << ['Client', 'Projects per Client']
user.clients.each do |p|
custom_arr << [p.name, p.projects.count]
end
return custom_arr
end
end
我强制添加我需要的标头,然后在JavaScript中使用一个非常简单的调用 -
var client_arr = <%= raw get_projects_per_client(current_user) %>
raw的目的是远程符号/报价替换。另外,你的字符串变为"
并打破JavaScript。
不确定这是否是正确的方式,但我很喜欢它的影响。
答案 1 :(得分:0)
您可以在单个查询中完成所有这些操作:
user.projects
.select("projects.name, COUNT(clients.id) AS clients_count")
.left_joins(:clients)
.group(:id)
.map { |project| [project.name, project.clients_count] }
您还可以为项目添加计数器缓存 - &gt;客户关系如下:
迁移:
class AddClientCounterCacheToProjects < ActiveRecord::Migration
def change
add_column :projects, :clients_count, :integer, default: 0, null: false
end
end
客户端模型:
class Client < ApplicationRecord
belongs_to :project, counter_cache: true
end
然后你可以查找项目的客户数,而不用像这样做N + 1:
project.clients.size
导入时使用.size
而非.count
,因为.count
将始终对您的数据库执行另一次查询。
这将最终看起来像这样:
user.projects.map { |project| [project.name, project.clients.size] }
使用project.clients.any?
,project.clients.empty?
等代码时,计数器缓存还可以节省资源。
如果您想为用户计算客户端数量,可以在用户模型上添加has many through
关系,如下所示:
class User < ApplicationRecord
has_many :projects
has_many :clients, through: :projects
end
然后你可以像这样得到客户:
user.clients.size