2012-03-14 3 views
35

Ho un modello chiamato argomento, che ha un nome come campo.Rails: come trovare un campo contenente una determinata stringa

Quindi dire che ho un termine che sto cercando, mela.

Se faccio un

Topic.find_by_name("apple") 

ottengo un record indietro con il nome mela. Va bene, ma come faccio a cambiare find_by_name in modo che possa trovare "succo di mela" e "mela" - in pratica, trovare nomi che contengono la query originale o corrispondere esattamente alla query originale?

Modifica: Grazie per tutta la risposta. Immagino che avrei dovuto essere un po 'più chiaro prima, ma cosa succede se voglio trovarlo con un nome variabile (ovviamente non ho intenzione di trovare il nome "mela" ogni volta :))?

Come si modifica l'argomento. Quindi qualcosa di simile ...

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

Aggiunto una modifica alla mia risposta relative al tuo ultimo modificare, fammi sapere se questo aiuta! – Deleteman

+0

Vedere il mio commento alla risposta di @ Alisher per la risposta alla tua domanda modificata. 'Topic.where (" nome come? "," # {@ Name}% ")' sarebbe un modo. –

risposta

82

penso che qualcosa del genere dovrebbe funzionare:

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

per ospitare per la tua modifica:

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

base di interpolazione di stringhe, che si sta utilizzando il valore di @search all'interno della stringa %%, quindi si @search = "apple" quindi si finisce con %apple%

+1

Pensi che questo metodo porti all'iniezione SQL? –

+2

Per quanto posso dire [qui] (http://rails-sqli.org/) il metodo 'where' non fa nulla per proteggere dall'iniezione SQL. Tuttavia, la domanda con veramente solo una risposta considerando se quella variabile è mai esposta all'input dell'utente, o attraverso un valore non salvato memorizzato, o direttamente. Questa dovrebbe essere la domanda di interesse. Il modo migliore per contrastare l'iniezione SQL è quello di disinfettare i valori al momento dell'applicazione, anche prima dello storage. – GKnight

+0

come non contenere una determinata stringa? – zx1986

0

Prova

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

Iniezione SQL nel primo esempio, dovrebbe essere 'Topic.where (" nome come? ","% Apple% ")'. Il secondo è OK. –

+0

ya hai ragione. – asitmoharna

+0

Puoi farlo anche in Rails 4+: 'Topic.find_by (" nome come? ","% Apple% ")' –

9

assomiglia nella Rails 3 si vorrebbe utilizzare il dove:

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

Non sei sicuro che funzioni - è "~ =" sql valido? O stai pensando al matcher con pattern di rubini "= ~". Se così non funzionerebbe qui in quanto non è sql –

+0

Sì, ho notato che nel post ho fatto riferimento e appena preso al valore nominale ... cambierò in LIKE ed essere al sicuro. Grazie! – ScottJShea

+5

L'operatore '~ =' funziona con PostgreSQL - è una corrispondenza regolare. Ma sì, la risposta di Scott dovrebbe funzionare. Potresti voler usare ILIKE, che fornisce una ricerca senza distinzione tra maiuscole e minuscole. –

7

Non mettere stringa direttamente in quel modo. Si chiama iniezione SQL. Si dovrebbe invece usare .where:

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

Si suppone che sia "nome come '?%'" O "nome come '%?%'" – varatis

+3

Questo non funzionerà esattamente come notato perché Rails citerà automaticamente la stringa . Avrai bisogno di virare su '%' prima della sostituzione, ad esempio 'Topic.where (" nome come? "," # {Params [: nome]}% ").' –

+0

Bella risposta. –

2

Con PostgreSQL è anche possibile utilizzare match operators:

Topic.where("name ~* ?", @search)