2015-09-17 9 views
5

Dies ist ein Problem, auf das ich regelmäßig stoße. Lassen Sie mich das anhand eines vereinfachten Beispiels erklären:Rails: Multiselect-Filterung mit einer leeren Option

Angenommen, ich möchte eine Suchseite anzeigen, auf der Ergebnisse durch Auswahl einer oder mehrerer Produktkategorien gefiltert werden können. In der Ansicht, das sieht aus wie:

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

nun in der Steuerung, ich habe so etwas wie:

@filtered_products = Product.all 

... 

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

... 
#etc 

Da es jedoch unmöglich ist, deaktivieren eine Mehrfachauswahl, wenn darauf geklickt hat, Es gibt eine leere Option. Wenn diese Option jedoch festgelegt ist, enthält params[:product_categories][""]. Dies führt dazu, dass die if-Anweisung ausgewertet wird, und als "" .to_i == 0 erhalten wir nur Produkte mit Kategorie 0 (was normalerweise keine ist, da ActiveRecord IDs von 1 in der Datenbank startet). Dies ist nicht das gewünschte Ergebnis, denn in der Tat wollen wir alle Produkte, wenn die leere Option ausgewählt ist.

Die Handhabung dieses Falles wird noch schwieriger, weil es möglich ist, versehentlich sowohl die leere Option als auch eine oder mehrere andere Optionen auszuwählen. Also muss auch dieser Fall behandelt werden.

ich mich verändert habe die if-Anweisung

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

Es funktioniert, aber dieser Code ist sehr hässlich. Ich frage mich, ob es eine schönere, trockenere, Schienen-ähnliche Art gibt, dies zu tun.

Antwort

4

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

end 
5

Versuchen Sie, wenn Sie nicht ein Kategorien haben ausgewählt Sie hidden_field gleiche wie product_categories hinzufügen können [""] mit Nullwert vor Ihrer Auswahl von Optionen zu vermeiden.

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

Dann, um damit umzugehen. Es muss nicht zugeordnet werden (&: ID), da "" in Abfrage automatisch in 0 generiert wird.

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

Dies ist, warum embedded array always showing in multiple select options. Ich hoffe, das macht deinen Code sauber.

4

Nur verbessern Florin 's Antwort ein wenig.

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