Ricerche condizionate in base alle categorie


#1

Salve a tutti,
la struttura del DB è la seguente.
ho 4 tabelle:
books
categories
authors
nationalities

books -> belongs_to: categories, authors, nationalities

quindi nella tabella books ci sono category_id, author_id e
nationality_id.

Nel sito è ovviamente possibile fare tutte le possibili scelte e quindi:
solo la categoria;
la categoria e l’autore;
categoria, autore e nazionalitÃ
etc…

Per fare una ricerca all’interno della tabella books in base ai
parametri selezionati ho scritto nel controller:

if @category==“tutti” and @nation==“tutte” and @author==“tutti”
@books=Book.find(:all,:order=>‘title’)
end

if not (@category==“tutti” and @nation==“tutte” and @author==“tutti”)
@books=Book.find(:all,:conditions=>[“category_id=? and nationality_id=?
and
author_id=?”,@selected_cat,@selected_nat,@selected_aut],:order=>‘title’)
end

if @nation==“tutte” and not (@category==“tutti” and @author==“tutti”)
@books=Book.find(:all,:conditions=>[“category_id=? and
author_id=?”,@selected_cat,@selected_aut],:order=>‘title’)
end

if @category==“tutti” and not (@nation==“tutte” and @author==“tutti”)
@books=Book.find(:all,:conditions=>[“nationality_id=? and
author_id=?”,@selected_nat,@selected_aut],:order=>‘title’)
end

if @author==“tutti” and not (@category==“tutti” and @nation==“tutte”)
@books=Book.find(:all,:conditions=>[“category_id=? and
nationality_id=?”,@selected_cat,@selected_nat],:order=>‘title’)
end

if @nation==“tutte” and @category==“tutti” and not @author==“tutti”
@books=Book.find(:all,:conditions=>[“author_id=?”,@selected_aut],:order=>‘title’)
end

if @nation==“tutte” and @author==“tutti” and not @category==“tutti”
@books=Book.find(:all,:conditions=>[“category_id=?”,@selected_cat],:order=>‘title’)
end

if @author==“tutti” and @category==“tutti” and not @nation==“tutte”
@books=Book.find(:all,:conditions=>[“nationality_id=?”,@selected_nat],:order=>‘title’)
end

Secondo voi come si può snellire il codice?

Grazie mille in anticipo!

Luigi


#2

2009/2/9 Luigi M. removed_email_address@domain.invalid:

non testato, ma dovrebbe funzionare:

conds = { }

conds[:category_id] = @selected_cat if @category != “tutte”
conds[:nation_id] = @selected_nat if @nation != “tutte”
conds[:author_id] = @selected_aut if @autor != “tutti”

@books = Book.find(:all, :conditions => conds, :order => ‘title’)


#3

Grazie mille per risposta.
Adesso non posso provare il codice però mi viene un dubbio:
scritto così sembra che “conds” possa essere uguale solo ad una delle
tre se non solo all’ultima condizione se questa è vera?
oppure si autoimplementa?

Grazie ancora


#4

2009/2/9 Luigi M. removed_email_address@domain.invalid:

Grazie mille per risposta.
Adesso non posso provare il codice però mi viene un dubbio:
scritto così sembra che “conds” possa essere uguale solo ad una delle
tre se non solo all’ultima condizione se questa è vera?
oppure si autoimplementa?

in ruby,

x if y

è equivalente a:
if y
x
end

quindi il codice che ti ho passato è equivalente a:

conds = { }

if @category != “tutte”
conds[:category_id] = @selected_cat
end

if @nation != “tutte”
conds[:nation_id] = @selected_nat
end

if @autor != “tutti”
conds[:author_id] = @selected_aut
end

solo che in quel modo mi sembra più chiaro.

vengono generate tutte e otto (2 scelte, vero o falso, elevato 3
domande)
possibilità.
pietro


#5

2009/2/9 Andrea C. removed_email_address@domain.invalid:

Personalmente trovo più leggibile:

conds = {}
conds.merge! {:category_id => @selected_cat} if @category != “tutte”
… e così via.

non mi piace.

In alternativa, proprio ieri ho scoperto squirrel
(http://www.thoughtbot.com/projects/squirrel/), che ti permette di scrivere:

@books = Book.find(:all) do
category_id == @selected_cat if @category != “tutte”

order_by title
end

questo sì che mi piace!

ma mi sembra di ricordare che in rails 2.3 ci sarà qualcosa di simile.


#6

On 2/9/09 12:04 PM, Pietro G. wrote:

@books = Book.find(:all, :conditions => conds, :order => ‘title’)


Ml mailing list
removed_email_address@domain.invalid
http://lists.ruby-it.org/mailman/listinfo/ml

Personalmente trovo più leggibile:

conds = {}
conds.merge! {:category_id => @selected_cat} if @category != “tutte”
… e così via.

In alternativa, proprio ieri ho scoperto squirrel
(http://www.thoughtbot.com/projects/squirrel/), che ti permette di
scrivere:

@books = Book.find(:all) do
category_id == @selected_cat if @category != “tutte”

order_by title
end

Andrea


#7

Pietro,
grazie mille il tuo codice funziona alla perfezione:

conds = { }

conds[:category_id] = @selected_cat if @category != “tutte”
conds[:nation_id] = @selected_nat if @nation != “tutte”
conds[:author_id] = @selected_aut if @autor != “tutti”

@books = Book.find(:all, :conditions => conds, :order => ‘title’)

Se posso vorre Approfittare ancora della vostra disponibilità :

dove posso trovare, in internet, una guida di riferimento che mostri
comandi come questi.
Ho il libro Agile Web D., in italiano acquistato, ma
informazioni di questo tipo non ce ne sono proprio.

Grazie ancora.

Luigi


#8

2009/2/9 Luigi M. removed_email_address@domain.invalid:

dove posso trovare, in internet, una guida di riferimento che mostri
comandi come questi.
Ho il libro Agile Web D., in italiano acquistato, ma
informazioni di questo tipo non ce ne sono proprio.

quando si tratta di sapere come si usano i vari metodi, non c’è niente
di meglio del reference.

di solito le leggo direttamente da api.rubyonrails.org. che so, voglio
sapere i metodi di activerecord, cerco su google class activerecord.
voglio sapere i metodi del controller, cerco class activecontroller.

ma la documentazione ce l’hai anche sul computer, basta che fai gem
server e ti colleghi a localhost:8808 e trovi la documentazione di
tutte le gem installate.

in inglese, purtroppo; in italiano non c’è praticamente niente.

questo quando so già più o meno cosa devi fare; quando invece cerco
ispirazione, cioè, quando non ho già in mente la soluzione, tutto sta
nel formulare la domanda nel modo giusto; una volta che lo si è fatto,
la risposta la si trova subito. per me il maggior aiuto sono i canali
irc e le ml in inglese: mi metto lì, cerco di riassumere il mio
problema nel modo più chiaro e conciso possibile, e quando sono pronto
a inviare cerco su google la frase che ho scritto; nove volte su
dieci, non ho più bisogno di chiedere.

spesso, però, la miglior documentazione possibile è il codice: più
si
acquista familiarità col framework, più spesso capita di voler / dover
dare un’occhiata ai sorgenti, cosa che aumenta ancora la
familiarità.
pietro


#9

Avrei un altro problema:
per generare un URL spider-friendly ho nella view la seguente linea di
comando:
selection_url(:nation=>@nation,:category=>@category,:author=>@author)

dove selection_url è definito nel file routes.rb come segue:

map.selection
‘libri/nazionalita/:nation/genere/:category/autore/:author/elenco.html’,
:controller=>‘book’, :action=>‘selection’

in tal modo possono essere generati degli url del tipo:

http://127.0.0.1:3000/libri/nazionalita/tutte/genere/commedia/autore/tutti/elenco.html

http://127.0.0.1:3000/libri/nazionalita/tutte/genere/commedia/autore/eliott-parker/elenco.html

http://127.0.0.1:3000/libri/nazionalita/inglese/genere/commedia/autore/eliott-parker/elenco.html

etc…

Sarebbe bello, però, nel caso in cui venga selezionata solo la categoria
o solo l’autore o solo la nazionalità o solo due di queste generare URL
del tipo:

http://127.0.0.1:3000/libri/genere/commedia.html

etc…

Mi ritrovo quindi a dover affrontare un problema simile a quello del
primo post
dove cioè dovrei generare 8 condizioni if…end e altrettante 8 routes.

Che mi suggerite?

Grazie mille.

Luigi