5

Powiedzmy mam tablicę (otrzymane od strony klienta) identyfikatorów:Korzystanie gdzie z szynami przygotowanej składni oświadczenie

myArray = [1,5,19,27]

I chciałbym zwrócić wszystkie elementy, dla których (wtórny) id znajduje się na tej liście.

W SQL byłoby to:

SELECT * FROM Items WHERE id IN (1,5,19,27)

Zdaję sobie sprawę, że mogę zrobić:

Item.where(id: [1,5,9,27]),

jednak już gdzie kwerendy, że to być dołączona na używa przygotowana składnia oświadczenia Item.where('myAttrib = ? AND myOtherAttrib <> ? AND myThirdAttrib = ?', myVal[0], myVa[1], myVal[2])

w związku z tym, co ja chciałoby się następująco:

Item.where('id IN ?', myArray)

jednak, że produkuje się błąd składni:

ActiveRecord::StatementInvalid: PG::Error: ERROR: syntax error at or near "1" LINE 1: SELECT "items".* FROM "items" WHERE (id in 1,2,3,4)

Jak można to obejść? Jaki jest właściwy sposób użycia, gdy z przygotowaną składnią instrukcji dla wyrażeń IN.

Odpowiedz

2

Trzeba zmienić zapytanie na następujące kwestie:

Item.where('id = ?', myArray) 

ActiveRecord następnie przekonwertować to do klauzuli jeśli myArray jest w rzeczywistości, tablicę.

6

skończyło się przy użyciu:

Item.where('id IN (?)', myArray)

0

Problem z użyciem surowego SQL to, że tracisz automatyczne Przestrzenie nazw nazw kolumn ów pod warunkiem za darmo przez Rails i AREL.

Używanie surowego sql może powodować problemy podczas łączenia i łączenia zapytań lub zakresów lub podczas łączenia.

Nie ma potrzeby stosowania SQL podczas korzystania IN:

Item.where(:id => myArray) # SELECT * FROM items WHERE id IN (...) 

myArray może być albo tablicą wartości lub tablicę Items lub pojedynczą wartość.

Szyny są wystarczająco inteligentne, aby zmienić SQL na to, co masz na myśli. W rzeczywistości, jeśli tablica zawiera nil, SQL będzie SELECT * FROM items WHERE (id IS NULL or id IN (...)). Jest to wyraźnie lepsze niż użycie surowego SQL, który jest statyczny i zdolny do radzenia sobie z pojedynczym przypadkiem użycia.

Jeśli Rails nie dostarczy Ci tego, czego potrzebujesz, możesz wrócić do AREL. Na przykład:

class Item 
    scope :with_category, ->(categories) { 
    where(arel_table[:category].in(categories)) 
    } 

    scope :filter, ->(a, b, c) { 
    not_b = arel_table[:myOtherAttrib].not_eq(b) 
    where(:myAttrib => a, :myThirdAttrib => c).where(not_b) 
    } 
end 

Item.with_category(['small', 'large']).filter(*myVal) 
Powiązane problemy