如何在Ransack中设置默认排序参数以避免nil类方法错误?
Rails 7 + Ransack 设置默认排序解决空参数报错
问题分析
报错undefined method '[]' for nil:NilClass的核心原因是:当列表页未携带排序参数时,params[:q]为nil,直接调用params[:q][:s]会触发空对象方法调用错误。同时需要保留用户通过Ransack选择的排序(包括distance排序),并设置默认排序规则。
解决方案1:安全获取排序参数并设置默认值
直接修改ParksController的index方法,使用dig安全获取排序参数,为空时使用默认值:
class ParksController < ApplicationController def index # 安全获取排序参数,无参数时使用默认排序 sort_param = params.dig(:q, :s) || "average_rating desc" @parks = @q.result(distinct: true) .includes(:visited_users, :favorited_users) # 关闭Geocoder默认的距离排序,避免覆盖自定义排序 .near(@user_coordinates, 100000000, order: false) .order(sort_param) .paginate(page: params[:page], per_page: 24) end end
说明:
params.dig(:q, :s)会在params[:q]为nil时返回nil,避免直接调用[]报错- 添加
order: false到near方法,确保自定义排序(包括用户选择的distance desc)生效
解决方案2:通过Ransack设置默认查询参数
修改ApplicationController的set_search方法,初始化Ransack时设置默认排序参数:
class ApplicationController < ActionController::Base before_action :set_search def set_search # 合并默认排序参数,用户已有排序参数则优先使用 search_params = params[:q].to_h.merge(s: "average_rating desc").compact_blank @q = Park.ransack(search_params) end end
然后修改ParksController的index方法,移除额外的order调用,并关闭near的默认排序:
class ParksController < ApplicationController def index @parks = @q.result(distinct: true) .includes(:visited_users, :favorited_users) .near(@user_coordinates, 100000000, order: false) .paginate(page: params[:page], per_page: 24) end end
说明:
compact_blank会移除哈希中的空值,确保用户传入的s参数优先级高于默认值- 关闭
near的默认排序后,Ransack的排序规则会完全生效,包括默认的average_rating desc和用户选择的distance desc等选项
为什么之前的尝试无效?
你之前设置@q.sorts = [...]后无效,是因为后续在index方法中调用了.order(params[:q][:s]),该语句会覆盖Ransack结果自带的排序规则。同时near方法默认添加的距离排序也会干扰自定义排序,需要通过order: false关闭。
内容的提问来源于stack exchange,提问作者Rebecca
相关产品推荐
相关产品推荐

