Rails合并多个ActiveRecord查询



有人能指出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格式(这样会更干净)。检查此处

最新更新