我使用分类模型在Projets和Categories之间建立了belongs_to
关系。 Projet class Client < ApplicationRecord
has_many :projets
end
class Category < ApplicationRecord
has_many :categorizations, dependent: :destroy
has_many :projets, through: :categorizations
end
class Categorization < ApplicationRecord
belongs_to :category
belongs_to :projet
end
class Projet < ApplicationRecord
belongs_to :client
has_many :categorizations, dependent: :destroy
has_many :categories, through: :categorizations
end
客户。
def listing
@projets_clients = Projet
.select("client_id")
.includes(:client)
.joins(:categorizations)
.where(categorizations: { category: @category })
.group("client_id")
@clients = []
@projets_clients.each do |p|
@clients << Client.includes(:projets).find(p.client_id)
end
end
对于特定类别,我想列出所有按客户分组的项目。 e.g。
(对于category_id = 3)
客户A. Projet 1 Projet 2
客户B Projet 3
客户C. Projet 4
到目前为止,我可以使用它,但只能使用两个查询(其中一个查询非常低效(n + 1问题)。
这是代码
var $actions = application.service('$actions', [
function() {
let _logout = function() {
$('#logoutForm').submit();
}
return {
**Logout() {**
_logout();
},
};
}]);
如果有人能提出更好的方法,我很乐意学习如何优化这一点,因为我自己找不到更好的方法。
感谢。
答案 0 :(得分:1)
有几种不同的方法可以做到这一点。对于复杂查询,我有时会发现编写和执行直接SQL更容易。但是对于您的情况,根据数据大小,您可以急切地加载数据并将其转换为哈希值。
注意:当我测试此代码时,我使用的是projects
而不是projets
。
@category = Category.includes(projects: [:client]).find(2)
@projects_by_client = @category.projects.group_by(&:client_id)
# In your view
<%- @projects_by_client.each do |client_id, projects| %>
<%= projects.first.client.name %>
<%- projects.each do |project| %>
<%= project.name %>
<% end %>
<% end %>
更加丰富的解决方案可能会将完整的sql与查询对象和演示者对象一起使用。我使用下面的代码创建了一个快速项目,输出就是你要找的。 p>
# app/controllers/clients_controller.rb
class ClientsController < ApplicationController
def show
result = ClientQuery.call(params[:id])
@presenter = ClientPresenter.new(result)
end
end
# app/services/client_query.rb
class ClientQuery
class << self
def call(client_id)
sql_query(client_id)
end
protected
def sql_query(client_id)
ActiveRecord::Base.
connection.
execute(
sanitized_sql_statement(client_id)
)
end
def sanitized_sql_statement(client_id)
ActiveRecord::Base.send(
:sanitize_sql_array,
[
sql_statement,
client_id
]
)
end
def sql_statement
<<-SQL
SELECT
c.id AS client_id,
c.name AS client_name,
p.name AS project_name
FROM
clients c
INNER JOIN
projects p ON p.client_id = c.id
INNER JOIN
categorizations cz ON cz.project_id = p.id
INNER JOIN
categories ct ON ct.id = cz.category_id
WHERE
ct.id = ?;
SQL
end
end
end
# app/presenters/client_presenter.rb
class ClientPresenter
attr_reader :clients
def initialize(data)
@clients = {}
process_sql_result(data)
end
private
def process_sql_result(data)
data.each do |row|
client_id = row['client_id']
@clients[client_id] ||= { client_name: row['client_name'] }
@clients[client_id][:projects] ||= []
@clients[client_id][:projects] << row['project_name']
end
end
end
# app/views/show.html.erb
<%- @presenter.clients.each do |client_id, client_presenter| %>
<h1><%= client_presenter[:client_name] %></h1>
<ul>
<%- client_presenter[:projects].each do |project_name| %>
<li><%= project_name %></li>
<% end %>
</ul>
<% end %>
这当然只是您在单个查询中呈现数据并展示数据的众多方法之一。