2015-09-17 73 views
5

這是我經常遇到的問題。讓我通過一個簡化的例子來解釋它:Rails:使用空白選項進行多選篩選

假設我想顯示一個搜索頁面,可以通過選擇一個或多個產品類別來篩選結果。在視圖中,這看起來像:

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

現在,在控制器中,我有這樣的:

@filtered_products = Product.all 

... 

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

... 
#etc 

然而,因爲它是不可能取消當點擊了多選,有一個空白選項。但是,當此選項設置時,params[:product_categories]包含[""]。這導致if語句評估,並且作爲「」to_i == 0,我們只得到類別爲0的產品(通常沒有,因爲ActiveRecord在數據庫中從1開始ID)。這不是理想的結果,因爲事實上,我們希望全部產品,當選擇空白選項。

處理這種情況更加困難,因爲可能意外地選擇了空白選項和一個或多個其他選項。所以這種情況也需要處理。

我已經改變了if語句來

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

它的工作原理,但是這個代碼是非常難看。我想知道是否有更好,更幹,像Rails的方式來做到這一點。

回答

4

嘗試

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

end 
5

當你有選擇,你可以添加hidden_field一樣product_categories沒有一個類別,以避免[""]與您之前選擇選項零值。

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

然後處理它。它不需要映射(&:id),因爲""將在查詢中自動生成爲0。

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

這些是爲什麼embedded array always showing in multiple select options。我希望這可以清理你的代碼。

4

只是改善Florin的回答了一下。

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