2015-09-17 7 views
5

Questo è un problema che sto incontrando regolarmente. Vorrei spiegarlo con un esempio semplificato:Rails: filtro multiselect con un'opzione vuota

Dire che voglio mostrare una pagina di ricerca in cui i risultati possono essere filtrati selezionando una o più categorie di prodotti. Dal punto di vista, questo appare come:

<%= select_tag("product_categories", options_from_collection_for_select(@product_categories, 'id', 'name'), multiple:true, include_blank:"(all categories)" %> 

Ora, nel controller, ho qualcosa di simile:

@filtered_products = Product.all 

... 

if params[:product_categories].present? 
    @filtered_products = @filtered_products.where(category_id: params[:product_categories].map(&:to_i)) 
end 

... 
#etc 

Tuttavia, come è impossibile deselezionare una selezione multipla quando ha cliccato, c'è un'opzione vuota. Ma, quando questa opzione è impostata, params[:product_categories] contiene [""]. Ciò si traduce nell'istruzione if da valutare e come "" .to_i == 0, otteniamo solo prodotti con categoria 0 (che di solito non è nessuno, poiché ActiveRecord avvia ID da 1 nel database). Questo non è il risultato desiderato, dato che in effetti vogliamo i prodotti tutti quando è selezionata l'opzione vuoto.

La gestione di questo caso è resa ancora più difficile dal momento che è possibile selezionare accidentalmente sia l'opzione vuota che una o più opzioni. Quindi questo caso deve essere gestito anche.

ho cambiato il se-dichiarazione per

if params[:product_categories].present? && params[:product_categories].any? && (params[:product_categories].length > 1 || params[:product_categories].first != "") 
    ... 
end 

Funziona, ma questo codice è molto brutto. Mi chiedo se ci sia un modo più bello, più SECCO, simile a Rails per farlo.

risposta

4

Prova

if params[:product_categories].reject!(&:empty?).any? 

end 
5

Quando hai categorie di quello selezionato è possibile aggiungere hidden_field stessa product_categories per evitare [""] con un valore pari a zero davanti ai tuoi selezionare le opzioni.

<%= hidden_field_tag "product_categories" %> 
<%= select_tag("product_categories", options_from_collection_for_select(@product_categories, 'id', 'name'), multiple:true, include_blank:"(all categories)" %> 

Quindi gestirlo. Non è necessario mappare (&: id) perché "" verrà generato automaticamente in 0 nella query.

if params[:product_categories] != [""] 
    @filtered_products = @filtered_products.where(category_id: params[:product_categories]) 
end 

Ecco perché embedded array always showing in multiple select options. Spero che questo faccia pulire il tuo codice.

4

Semplicemente migliorando la risposta di Florin un po '.

params[:product_categories].reject!(&:empty?).any? if params[:product_categories].length > 1