如何使用Ransack实现多值数组搜索并修复to_i报错?
问题分析与解决方案
关于to_i报错的原因
Ransack的_eq查询条件(比如你用的dance_styles_id_eq)是为单个值匹配设计的,它内部会尝试将传入的参数调用to_i转换为整数类型,以便和数据库中的ID字段匹配。但当你开启multiple: true后,表单提交的是一个数组(比如["", "5", "6"]),而数组对象并没有to_i方法,所以触发了这个错误。
修复步骤
1. 修改表单的查询字段名
把单值匹配的_eq后缀改成支持数组的_in后缀,这是Ransack专门用来处理多值包含查询的条件:
<div class="dancestyle"> <%= f.label "Dance style", class: "form-label" %> <%= f.select(:dance_styles_id_in, DanceStyle.all.pluck(:name, :id), { :include_blank => "All dance styles" }, { class: "form-select", id: "select-dancestyle", multiple: true, placeholder: "Any dance style" }) %> </div> <div class="eventtype"> <%= f.label "Event Type", class: "form-label" %> <%= f.select :event_type_id_in, EventType.all.pluck(:name, :id), { :include_blank => "All event types" }, { id: "select-artist", placeholder: "Any event type", class: "form-select", multiple: true } %> </div>
(注:活动类型的select也添加了multiple: true,如果需要多值筛选的话)
2. 控制器中清理无效参数
提交的数组会包含空字符串(来自表单的include_blank选项),需要在Ransack查询前过滤掉这些空值,避免无效查询:
def index if params[:q] params[:q][:combinator] = "and" params[:q][:groupings] = [] # 清理舞蹈风格的空值参数 if params[:q][:dance_styles_id_in].present? params[:q][:dance_styles_id_in] = params[:q][:dance_styles_id_in].reject(&:blank?) end # 清理活动类型的空值参数(如果开启了多选) if params[:q][:event_type_id_in].present? params[:q][:event_type_id_in] = params[:q][:event_type_id_in].reject(&:blank?) end split_geo = params[:q][:address_or_city_or_state_or_country_or_continent_cont_all].split(/(,\s)+/) split_geo.map! do |a| I18n.transliterate a end split_geo.each_with_index do |word, index| params[:q][:groupings][index] = { address_or_city_or_state_or_country_or_continent_cont_all: word } end end @q = Event.ransack(params[:q]) @events = @q.result(distinct: true) .where(event_status_id: 1) end
3. 可选:空参数的默认行为
如果用户没有选择任何选项(数组为空),Ransack会自动忽略这个查询条件,返回所有符合其他条件的记录,无需额外处理。
内容的提问来源于stack exchange,提问作者Ogarocious
相关产品推荐
相关产品推荐

