2017-11-18 9 views
2

찾을 :레일 내가 다음과 같습니다 해시의 배열이</p> <p>(AN <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을 사용하면 아무런 이점이 없습니다.

나는 or와 함께 첫 번째 조건 및 체인에 대한 다른 모든 조건을 where를 사용 (그리고 레일 살균의 관심과 무거운 보자) 것입니다 : 당신은 정확했다

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.drop (1) .inject (Model.where (array.first)) {| m, h | m.or ​​(Model.where (h))}'는 배열을 변경하지 않고 동일한 작업을 수행합니다. – brainbag

+1

그 문제를 해결하기 위해 내 대답이 업데이트되었습니다. – spickermann

4

Arel을 사용해도 SQL을 사용하지 않고는이 작업을 수행 할 수 없다고 생각합니다.

배열은 따옴표로 묶을 수 없기 때문에 위생적으로 처리 할 수 ​​있도록 바보 같은 것들을해야합니다. 이것은 위대한 솔루션이 아니지만 작동하는 솔루션입니다.

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

끝 부분에있는 정말 기발한'[0 ..- 2]'쉼표 제거를 피하기 위해'values ​​= ([ '(?)'] * conditions.length) .join (',')'을 사용하십시오. 즉시 쓰레기를 버리지 않는 것이 낫습니다. – tadman

+1

@tadman 일반적으로 좋은 지적이지만 이것은 의도적 인 것입니다. 대체 배열 구문은 내가 사용한 문자열 조각보다 3.71x 느립니다. 꽤 예쁘지는 않지만 좀 더 연기적입니다. – brainbag