2017-11-18 215 views
2

導軌找到使用哈希數組</p> <p>我有散列的數組,看起來像這樣(使用<code>in</code>條款領域的選擇查詢通過對)記錄

[ {product_id: 7629, group_id: 4}, {product_id: 8202, group_id: 3} ]

我會想要返回的是Items表中與數組中的一對字段匹配的所有記錄。

在SQL它會像這樣被檢索:

SELECT * 
FROM items 
WHERE (product_id, group_id) IN (VALUES (7629,4), (8202,3)) 

,但我有麻煩了軌道.where條款這樣做。這甚至有可能嗎?

回答

3

我看到在使用SQL的IN在這種情況下,沒有任何好處。

我會用where爲第一條件和鏈上的所有其他條件與or(讓Rails的照顧消毒和重型起重):

array = [{ product_id: 7629, group_id: 4 }, { product_id: 8202, group_id: 3 }] 
array[1..-1].inject(Model.where(array[0])) { |m, h| m.or(Model.where(h)) } 
+1

不錯!這比我提出的要好得多。然而,它正在用'array.shift'修改'array',我認爲這不是理想的。 (array.first)){| m,h | m.or(Model.where(h))}''會做同樣的事情而不改變數組。 – brainbag

+1

更新了我的答案以解決該問題。 – spickermann

4

我想不出任何方法來做到這一點,而不訴諸於SQL,即使與Arel。

由於數組不能被引用,我們必須做一些愚蠢的事情,仍然允許它被消毒。這不是一個偉大的解決方案,但它是一個工作。

your_hashes = [ {product_id: 7629, group_id: 4}, {product_id: 8202, group_id: 3} ] 

# turn hashes into simple value array 
conditions = your_hashes.map { |h| [ h[:product_id], h[:group_id] ] } 
=> [[7629, 4], [8202, 3]] 

# create a list of "(?)" values that will allow the conditions to be passed in 
values = ("(?)," * conditions.length)[0..-2] 
=> "(?),(?)" 

# use it to look up the values 
Model.where("(product_id, group_id) IN (VALUES #{values})", *conditions) 

# this is the generated sql: 
SELECT "models".* FROM "models" WHERE ((product_id, group_id) IN (VALUES (7629,4),(8202,3))) 
+1

你是正確的,我不得不刪除我的答案。 –

+0

考慮使用'values =(['(?)'] * conditions.length).join(',')'來避免真正古怪的'[0..- 2]'逗號分離事物。最好不要把垃圾立即清除。 – tadman

+1

@tadman這通常是一個好點,但這是故意的。該替代陣列語法比我使用的字符串切片慢3.71倍。它不是很漂亮,但它性能相當高。 – brainbag

相關問題