Rails 5.1按日期范围+用户ID筛选支出数据无结果求助
让我一步步帮你排查这个问题:
第一个核心问题:参数传递不匹配
你前端表单里的user_id参数是直接挂在params根节点下的,但你的SpendingSearch初始化时只接收params[:search]——这就导致@user_id永远是nil,自然带用户ID筛选时出不来结果。
看你的前端代码:
<%= select_tag :user_id, options_from_collection_for_select(User.all, :id, :firstname, params[:user_id]), include_blank: true, class: 'form-control col-2 d-inline-block' %>
这里的select_tag的name是:user_id,提交后参数会是params[:user_id],但你的SpendingSearch.new只拿了params[:search],完全没用到这个参数。
修复参数传递:
把user_id的输入框放到search命名空间下,修改select_tag的name:
<%= select_tag "search[user_id]", options_from_collection_for_select(User.all, :id, :firstname, params.dig(:search, :user_id)), include_blank: true, class: 'form-control col-2 d-inline-block' %>
这样提交后,user_id就会出现在params[:search]里,能被SpendingSearch正确接收。
第二个核心问题:Scope查询的硬编码条件
现在即使参数传对了,你的scope方法还有个问题:不管user_id有没有值,都会强制加上AND user_id = ?的条件。如果用户没选用户ID(即user_id为空),SQL会变成user_id = NULL——这在SQL里是永远匹配不到结果的(因为判断NULL要用IS NULL,而且我们希望没选用户时不做这个筛选)。
修复Scope查询逻辑:
修改SpendingSearch的scope方法,动态拼接条件:
def scope scope = Spending.where("date BETWEEN ? AND ?", @date_from, @date_to) # 只有当user_id存在且不为空时,才添加用户筛选条件 scope = scope.where(user_id: @user_id) if @user_id.present? scope end
这样当用户没选用户ID时,就不会加上这个条件,保留日期筛选的逻辑;选了用户ID时,才会同时筛选对应的用户支出。
额外的语法问题:日期解析的Rescue写法
你的parsed_date方法里的rescue写法有语法错误,应该改成:
def parsed_date(date_string, default) Date.parse(date_string) rescue ArgumentError, TypeError then default # 或者更兼容的写法: # Date.parse(date_string) # rescue ArgumentError, TypeError # default end
原来的写法Ruby会报错,导致日期解析可能出问题。
最后验证控制器逻辑
你的控制器index方法没问题,保持原样即可:
def index @search = SpendingSearch.new(params[:search]) @spendings = @search.scope end
做完这些修改后,带用户ID的筛选应该就能正常工作了,同时空用户ID时也不会影响日期筛选的结果。
内容的提问来源于stack exchange,提问作者Asso

