Rails项目无法按指定格式从数据库获取检查数据求助
Rails数据查询格式问题排查与解决
问题背景
我有一个Rails应用,包含3个模型,无法按所需格式从数据库获取数据。
Rails模型
- Investigation:id, name, created_at, updated_at
- Appointment:id, patient_id, investigation_date, ...
- Result:investigation_id, appointment_id, findings
模型关联
Appointment has_many :resultsResult belongs_to :appointment,Result belongs_to :investigation
表结构片段
create_table "appointments", charset: "utf8mb4", force: :cascade do |t| t.bigint "patient_id", null: false t.date "investigation_date" end create_table "results", charset: "utf8mb4", force: :cascade do |t| t.bigint "appointment_id", null: false t.bigint "investigation_id", null: false t.string "findings" end create_table "investigations", charset: "utf8mb4", force: :cascade do |t| t.string "name" t.boolean "status", default: true end
期望的UI表格格式
表头固定为:检查日期(来自Appointment表)、检查项名称1(对应Result的findings)、检查项名称2(对应Result的findings)……
示例输出:
20-May-2021 100, 120, ....
20-June-2021 90, 120, ....
现有尝试代码
data = {} result = [] appointments = Appointment.where("patient_id = ? and investigation_date IS NOT NULL", params[:p_id]).order("investigation_date desc").last(5) appointment_id = appointments.pluck(:id) results_data = Result.where(appointment_id: appointments.pluck(:id)).includes(:investigation) appointments.each do |app| results_data.each do |data| result << data.findings end data[app.investigation_date.strftime("%d-%b-%Y")] = result end
当前问题
现有代码无法得到正确格式的数据;参考@Lukas的建议调整后,仍存在数据与表头不匹配的问题(如"okay"对应表头的"E","90"对应表头的"M"),请求排查错误并提供解决方案。
问题排查与解决方案
现有代码的核心问题
- 循环逻辑错误:遍历每个
appointment时,把所有results_data里的结果都塞进同一个数组,没有筛选当前appointment对应的结果 - 变量命名冲突:循环内的
data变量和外层存储最终结果的data哈希重名,导致逻辑混乱 - 未按表头顺序匹配数据:没有固定
Investigation的顺序,导致每个日期对应的检查结果和表头的检查项无法一一对应
修正后的代码实现
# 1. 先获取所有需要展示的检查项(作为表头,固定顺序,可按需过滤,比如只取启用状态的) investigations = Investigation.where(status: true).order(:name).to_a # 提取表头名称,用于UI展示 headers = ["检查日期"] + investigations.pluck(:name) # 2. 获取目标患者的最近5次有效检查预约,预加载关联数据避免N+1查询 appointments = Appointment .where(patient_id: params[:p_id], investigation_date: !nil) .order(investigation_date: :desc) .last(5) .includes(results: :investigation) # 3. 整理每个预约的检查结果,严格按表头顺序匹配 formatted_data = {} appointments.each do |app| # 将当前预约的结果转成investigation_id => findings的哈希,快速查找 app_results = app.results.index_by(&:investigation_id) # 按表头检查项顺序提取结果,无结果则留空或显示N/A findings = investigations.map do |investigation| app_results[investigation.id]&.findings || "" end # 存储日期对应的结果数组 formatted_data[app.investigation_date.strftime("%d-%b-%Y")] = findings end
代码说明
- 先固定
Investigation的排序规则,确保表头与每行结果的位置完全对应 - 使用
includes预加载关联数据,优化查询性能 - 用
index_by将当前预约的结果转为哈希,通过investigation_id快速匹配对应的检查项结果 - 遍历预约时仅处理当前预约的结果,避免数据交叉混乱
内容的提问来源于stack exchange,提问作者Vibhoo Mishra
相关产品推荐
相关产品推荐

