ruby-on-rails - rails : multiselect filtering with a blank option

标签 ruby-on-rails activerecord multi-select

这是我经常遇到的一个问题。让我通过一个简化的例子来解释它:

假设我想显示一个搜索页面,可以通过选择一个或多个产品类别来过滤结果。在 View 中,这看起来像:

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

现在,在 Controller 中,我有类似的东西:
@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 开始 ids)。这不是我们想要的结果,因为实际上我们想要 全部 选择空白选项时的产品。

处理这种情况变得更加困难,因为可能会意外选择空白选项和一个或多个其他选项。所以这个案例也需要处理。

我已将 if 语句更改为
if params[:product_categories].present? && params[:product_categories].any? && (params[:product_categories].length > 1 || params[:product_categories].first != "")
   ...
end

它有效,但这段代码非常难看。我想知道是否有更好、更 DRY、类似 Rails 的方法来做到这一点。

最佳答案

当您没有选择任何一个类别时,您可以添加 hidden_fieldproduct_categories避免 [""]在您选择的选项之前为 nil 值。

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

然后去处理。不需要 map(&: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 .我希望这能让你的代码变得干净。

关于ruby-on-rails - rails : multiselect filtering with a blank option,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32626179/

相关文章:

ruby-on-rails - Rails 'to_sql' 没有 '\'

ruby-on-rails - Ruby on Rails 调用对象的方法

ruby-on-rails - ActiveRecord::Base before_validation with conditional not triggered

ruby-on-rails - Rails where 语句与 datetime.month

ruby-on-rails - Rails - 在连接表中创建/销毁记录

Jquery多选: How to know which value was selected/deselected

jQuery 和多选

c# - 多选 WinForms 列表框的双向绑定(bind)?

ruby-on-rails - 在Rails/ActiveRecord和旧版架构中避免 “Single Table Inheritance”

ruby-on-rails - Rails 5 API : Globally Set config. time_zone 到 UTC