2010-12-13 13 views
103

chcę zrobić coś takiego:Jak wykonać zapytanie LIKE w Arelu i Railsach?

SELECT * FROM USER WHERE NAME LIKE '%Smith%'; 

moja próba w AREL:

# params[:query] = 'Smith' 
User.where("name like '%?%'", params[:query]).to_sql 

Jednak ta postać:

SELECT * FROM USER WHERE NAME LIKE '%'Smith'%'; 

Arel owija ciąg kwerendy 'Smith' poprawnie, ale ponieważ jest to instrukcja LIKE, nie działa.

Jak wykonać zapytanie LIKE w Arel?

P.S. Premia - Próbuję skanować dwa pola na stole, zarówno nazwę, jak i opis, aby sprawdzić, czy są jakieś dopasowania do zapytania. Jak by to działało?

+1

zaktualizowałem odpowiedź AREL do premii. –

Odpowiedz

253

w ten sposób można wykonać jak kwerendy w AREL:

users = User.arel_table 
User.where(users[:name].matches("%#{user_name}%")) 

PS:

users = User.arel_table 
query_string = "%#{params[query]}%" 
param_matches_string = ->(param){ 
    users[param].matches(query_string) 
} 
User.where(param_matches_string.(:name)\ 
         .or(param_matches_string.(:description))) 
+1

Zgadza się. Oba podejścia powinny działać. Ale ten używa API Arel bardziej bezpośrednio. Jest to ważne, jeśli chcesz wykorzystać pełną moc Arel, np. do konstruowania złożonych zapytań. – rlkw1024

+9

W przeciwieństwie do używania 'where (" name like? ", ...)', to podejście jest bardziej przenośne w różnych bazach danych. Na przykład, spowoduje to użycie 'ILIKE' w zapytaniu względem bazy danych Postgres. – dkobozev

+19

jest chroniony przed zastrzykami SQL? – sren

114

Spróbuj

User.where("name like ?", "%#{params[:query]}%").to_sql 

PS.

q = "%#{params[:query]}%" 
User.where("name like ? or description like ?", q, q).to_sql 

Aaand minęło dużo czasu, ale @ cgg5207 dodany modyfikację (przeważnie użyteczne, jeśli masz zamiar szukać długo nazwanych lub wielu długich nazwie parametry albo jesteś zbyt leniwy, aby wpisać)

q = "%#{params[:query]}%" 
User.where("name like :q or description like :q", :q => q).to_sql 

lub

User.where("name like :q or description like :q", :q => "%#{params[:query]}%").to_sql 
+9

W jaki sposób Railsy wiedzą, aby nie ominąć '%' w podstawionym ciągu znaków? Wygląda na to, że jeśli chcesz tylko jednostronnego symbolu wieloznacznego, nic nie powstrzyma użytkownika przed przesłaniem wartości zapytania, która zawiera '%' na obu końcach (wiem, że w praktyce, Railsy zapobiegają wyświetlaniu '%' w ciągu zapytania , ale wydaje się, że powinna istnieć ochrona przed tym na poziomie ActiveRecord). –

+8

Czy to nie jest podatne na ataki SQL injection? – Behrang

+6

@Behrang nr 8) User.where ("nazwa jak% # {parametry [: zapytanie]}% lub opis jak% # {parametry [: zapytanie]}%"). To_sql byłby podatny na atak, ale w formacie I show, Railsy wymykają się z params [: query] –

3

odpowiedź Reubena Mallaby może zostać skrócony do dalszego korzystania powiązań parametrów:

User.where("name like :kw or description like :kw", :kw=>"%#{params[:query]}%").to_sql 
Powiązane problemy