Rails - 在视图(或帮助程序)中删除子记录的名称

时间:2017-10-14 03:02:42

标签: ruby-on-rails postgresql

我有三级关系。

用户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;

此查询返回我需要的确切结果。

2 个答案:

答案 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的目的是远程符号/报价替换。另外,你的字符串变为&quot;并打破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