我正在构建一个Rails 5应用程序,在这个应用程序中,我得到了四个模型。 用户,报告,行程和费用。
用户has_many报告,行程和费用 报告has_many许多旅行和费用。
我想获得一个JSON响应,其中包含用户本月进行的所有行程和费用,并按报表分组。
我可以这样做,但是我只需要报告的ID和标题(在分组时),现在我只得到对象名称。
我使用此方法(位于用户模型中):
def grouped_reports
trips = self.trips
expenses = self.expenses
items = trips + expenses
items.group_by(&:report)
end
JSON的输出是这样的:
{
"#<Report:0x007fa225163ba8>": [{
"id": 12,
"account_id": 20,
"user_id": 92,
"vehicle_id": null,
"ttype": null,
"description": "saf",
"start_latitude": 57.4874919,
"start_longitude": 12.0761927999999,
"end_latitude": 59.3293235,
"end_longitude": 18.0685808000001,
"start_address": "Chicago",
"end_address": "New york",
"distance": 490,
"time": null,
"status": "pending",
"registered_at": "2018-08-24T02:00:00.000+02:00",
"approvals_count": 0,
"rejections_count": 0,
"created_at": "2018-08-24T22:39:22.637+02:00",
"updated_at": "2018-08-24T22:39:22.637+02:00",
"report_id": 79,
"return_trip": null,
"triptype_id": 10
},
{
"id": 13,
"account_id": 20,
"user_id": 92,
"cost": 100,
"etype": null,
"description": "sdsd",
"start_address": null,
"end_address": null,
"distance": null,
"reimbursable": false,
"status": "pending",
"registered_at": "2018-08-08T00:00:00.000+02:00",
"created_at": "2018-08-24T22:39:40.343+02:00",
"updated_at": "2018-08-24T22:39:40.343+02:00",
"approvals_count": 0,
"rejections_count": 0,
"report_id": 79,
"expensetype_id": 15
}
]
}
我有两点需要改进。
更新,这行得通,但是在性能方面是否正确?
不仅性能,它实际上是否将报告标题用作分组因子?这样做不好,因为报告可能共享相同的标题。我想按report_id分组,但显示报告标题。
def grouped_reports
trips = self.trips
expenses = self.expenses
items = trips + expenses
items.group_by{ |t| [t.report.id, t.report.title] }
end
答案 0 :(得分:1)
代码将根据您要输出的JSON格式而有所不同。
我通常使用json生成器,例如Api
,但这次我建议使用数组和哈希结构。
jbuilder
class User < ApplicationRecord
has_many :reports
has_many :expenses
has_many :trips
def grouped_reports
start_date = Time.current.beginning_of_month
monthly_trips = trips.where('created_at >= ?', start_date)
monthly_expenses = expenses.where('created_at >= ?', start_date)
report_ids = (monthly_trips.map(&:report_id) + monthly_expenses.map(&:report_id)).uniq
reports = Report.where(id: report_ids)
reports.map do |report|
{
id: report.id,
title: report.title,
trips: trips.select {|t| t.report_id == report.id},
expenses: expenses.select {|e| e.report_id == report.id}
}
end
end
end
和trips
结合到一个数组中进行分组,但是最好不要将不同类型的JSON放入同一数组中。对于expenses
和trip
使用散列格式和单独的密钥是安全的。expense
进行过滤。where
和trips
使用includes
来获取reports
,但是从性能的角度来看,最好获取相关的{{1 }}。如果要进一步提高性能,请仅使用expenses
方法缩小在输出JSON时使用的列。如果输出大量记录,这将是一个巨大的进步。