有人能指出ActiveRecord是如何从左外部联接查询生成嵌套哈希的吗?
我正在急切地加载一个复杂的查询,其中需要将不同的WHERE子句应用于has_many关联表。当Rails生成查询以获取与应用条件的关联时,我没有得到预期的结果。
我能够为驱动表和has_many关联分别构建分段的结果。现在我需要将关联表的结果合并到驱动表中。
或者更简单地说,我在一个应用程序中有以下表格。
Items
___________________
| id | item_name |
___________________
| 1 | "Item One" |
| 1 | "Item One" |
| 1 | "Item One" |
| 1 | "Item One" |
| 1 | "Item One" |
___________________
Inventories
_________________
| id | quantity |
_________________
| 1 | 10 |
| 1 | 10 |
| 1 | 10 |
| 1 | 10 |
| 1 | 10 |
_________________
Transactions
_________________________________________
| id | item_id | tran_status | tran_qty |
_________________________________________
| 1 | 1 | "ordered" | 1 |
| 2 | 1 | "picked" | 1 |
| 3 | 1 | "ordered" | 4 |
| 4 | 1 | "canceled" | 5 |
| 5 | 1 | "ordered | 2 |
_________________________________________
Adjustments
_______________________________________
| id | item_id | adj_status | adj_qty |
_______________________________________
| 1 | 1 | "adjusted" | 1 |
| 4 | 1 | "canceled" | 1 |
_______________________________________
我正试图以以下格式(使用JBuilder)为AJAX操作创建一个JSON响应。
[{"id": 1,
"name": "Item One",
"inventory": {"quantity": 10},
"transactions": [ {"tran_status": "Ordered", "tran_qty": 1},
{"tran_status": "Picked", "tran_qty": 1},
{"tran_status": "Ordered", "tran_qty": 4},
{"tran_status": "Ordered", "tran_qty": 2} ],
"adjustments": [ {"adj_status": "Adjusted", "adj_qty": 1} ]
}
]
请注意,状态为"已取消"的记录将被排除在外
既然这可能会被多个项目请求,我想在查询过程中进行一次急切的加载。
但是,以下查询不起作用。Rails生成一个左外部联接查询,这会破坏聚会。
Item.includes(:inventory).
includes(:transactions).
where("transactions.status not in ('canceled')").
references(:transactions).
includes(:adjustments).
where("adjustments.status not in ('canceled')").
references(:adjustments).
where(id: params[:item])
因此,我要做的是分三步执行查询,并在最后创建一个散列或Openstruct,以便在JBuilder中进行迭代。
items = Item.includes(:inventory).
item_ids = items.collect(&:id)
trans = Transaction.where(item_id: item_ids).where("status not in ('canceled')")
adjs = Adjustment.where(item_id: item_ids).where("status not in ('canceled')")
现在我想将所有这些合并到一个散列数组中。
我意识到Rails会在内部做这样的事情,并考虑利用现有的知识,而不是用我有限的知识构建一种效率较低的方法。
如有任何帮助,我们将不胜感激。
更新
这个问题是在我自己试图建立一个解决方案的背景下提出的。核心问题是让Rails生成条件应用于关联表的查询。公认答案是建立与条件关联的建议(可以在公认答案的讨论线程中找到)。
如果我说得对,您需要迭代项目:
items = Item.includes(:inventory)
result = []
items.each do |i|
result << {
:item => i,
:trans => Transaction.where(item_id: i.id ).where("status not in ('canceled')"),
:adjs => Adjustment.where(item_id: i.id).where("status not in ('canceled')")
}
end
或者你可以通过一次收集将其放入阵列中:
result = Item.includes(:inventory, :transactions, :adjustments).collect { |i| i,
i.transactions.where("status not in ('canceled')"),
i.adjustments.where("status not in ('canceled')")
}
,前提是您已正确设置关联
require 'json'
hash_arr = []
Item.includes(:inventories,:transactions,:adjustments).all.each do |item|
hash = {"id"=>item.id,
"name"=>item.name,
"inventory"=>item.inventories.count,
"transactions"=>item.transactions.select("tran_status,tran_qty").collect{ |x|
{:tran_status=>x.tran_status,:tran_qty=>x.tran_qty}
},
"adjustments"=>item.adjustments.select("adj_status,adj_qty").collect{|x| {:adj_status=>x.adj_status,:adj_qty=>x.adj_qty}
}
}
hash_arr.push hash
end
hash_arr.to_json
希望这符合你的要求
或者,您可以使用as_json
并指定自己的JSON格式(这样会更干净)。检查此处