2012-03-14 9 views
35

Mam model o nazwie Temat, który ma nazwę jako pole.Szyny: Jak znaleźć_przez pole zawierające określony ciąg

Powiedzmy, że mam termin, którego szukam, jabłko.

Jeśli robię

Topic.find_by_name("apple") 

wrócę z nazwą jabłko rekord. To dobrze - ale jak zmienić find_by_name, aby mógł znaleźć "sok jabłkowy", a także "jabłko" - po prostu, znaleźć nazwy, które zawierają oryginalne zapytanie lub dokładnie pasują do pierwotnego zapytania?

Edytuj: Dzięki za wszystkie odpowiedzi. Sądzę, że powinienem być trochę bardziej przejrzysty wcześniej, ale co jeśli chcę znaleźć pod zmienną nazwą (oczywiście nie będę chciał znaleźć nazwy "jabłko" za każdym razem :))?

W jaki sposób mogę manipulować tematem, aby się do tego dostosować? Więc coś ...

@topic = Topic.where(......., @name) 
+0

Dodane zmienił się moją odpowiedź związanej swojej najnowszej edycji, daj mi znać, jeśli to pomaga! – Deleteman

+0

Zobacz mój komentarz do odpowiedzi @ Alisher na odpowiedź na twoje edytowane pytanie. 'Topic.where (" name like? "," # {Name}% ")' byłoby jednym ze sposobów. –

Odpowiedz

82

Myślę, że coś jak to powinno działać:

Topic.where("name like ?", "%apple%") 

aby pomieścić dla EDIT:

Topic.where("name like ?", "%#{@search}%") 

podstawowe interpolacji strun używasz wartość @search w ciągu znaków %%, czyli @search = "apple", a następnie kończysz z %apple%

+1

Czy uważasz, że ta metoda prowadzi do wstrzyknięcia SQL? –

+2

O ile mogę powiedzieć [tutaj] (http://rails-sqli.org/), metoda 'where' nie chroni przed iniekcją SQL. Jednak odpowiedź na to pytanie może być prawdziwa, biorąc pod uwagę, czy zmienna ta jest kiedykolwiek narażona na dane wprowadzone przez użytkownika, czy to przez zapisaną, niesanizowaną wartość, czy bezpośrednio. To powinno być kwestia zainteresowania. Najlepszym sposobem przeciwdziałania iniekcji SQL jest dezynfekcja wartości po wprowadzeniu aplikacji, nawet przed przechowywaniem. – GKnight

+0

co powiesz na niezawierający określonego ciągu? – zx1986

0

Spróbuj

Topic.where("name like ?",'%apple%') 
Topic.find(:all, :conditions => ["name like ?","%apple%"]) 
+0

SQL injection w pierwszym przykładzie powinno być 'Topic.where (" name like? ","% Apple% ")'. Druga jest w porządku. –

+0

ya, masz rację. – asitmoharna

+0

Możesz to również zrobić w Railsach 4+: 'Topic.find_by (" name like? ","% Apple% ")' –

9

Wygląda na Rails 3 co chcesz używać, jeżeli:

Topic.where("name ILIKE ?", "%apple%") 
+1

Nie wiesz, czy to by działało - czy "~ =" poprawny sql? A może myślisz o matującym wzór ruby ​​"= ~". Jeśli tak, to nie działałoby tutaj, ponieważ nie jest to sql. –

+0

Tak, zauważyłem, że we wpisie, do którego się odwołałem i po prostu przyjąłem go w wartości nominalnej ... Zamienię się JAK I będę bezpieczny. Dzięki! – ScottJShea

+5

Operator '~ =' działa dla PostgreSQL - jest to dopasowanie do wyrażenia regularnego. Ale tak, odpowiedź Scotta powinna zadziałać. Możesz użyć ILIKE, która zapewnia wyszukiwanie bez rozróżniania wielkości liter. –

7

Nie wkładać ciąg bezpośrednio tak. Nazywa się SQL injection. Należy zamiast tego użyć .where:

Topic.where("name like '?%' ", params[:name]) 
+0

Czy to ma być "nazwa jak"?% "" Lub "nazwa jak"%?% "" – varatis

+3

To nie zadziała dokładnie tak, jak wspomniałem, ponieważ Railsy automatycznie zacytują ciąg znaków . Będziesz musiał zająć się '%' przed podstawieniem, na przykład 'Topic.where (" name like? "," # {Params [: name]}% ").' –

+0

Piękna odpowiedź. –

2

Z PostgreSQL można również użyć match operators:

Topic.where("name ~* ?", @search) 
Powiązane problemy