Rails技术问题:如何从搜索表单获取并转换日期参数
解决Rails航班搜索表单的日期参数查询问题
嘿,我看你遇到了两个头疼的问题:首次加载页面时的nil类型转换错误,以及日期格式不匹配导致查不到正确航班。咱们一步步搞定它:
1. 先搞定"No implicit conversion of nil into String"错误
这个错出在页面刚打开还没提交表单的时候——此时params[:date]是nil,你直接把它传给DateTime.strptime,自然会报错说“不能把nil转成字符串”。所以得先判断参数是否存在,再执行查询逻辑:
修改flights_controller.rb里的index方法:
def index @airport_options = Airport.all.map { |a| [a.code, a.id] } @passengers = (1..4).to_a # 重点修正:生成日期选项时,存完整的ISO格式日期作为提交值,显示友好格式给用户 @dates_options = Flight.order('date ASC').pluck(:date).map do |date| [date.strftime("%d %b %H:%M"), date.iso8601] # 左边是用户看到的文本,右边是实际提交的参数 end # 只有当表单提交的关键参数都存在时,才执行查询 if params.values_at(:start_airport, :finish_airport, :date).all?(&:present?) # 解析ISO格式的日期字符串,不会丢失年份/时区 target_date = DateTime.iso8601(params[:date]) # 如果你想查当天所有航班(而不是精确到分的某一班),用日期范围查询更合理 @flights = Flight.where( start_airport_id: params[:start_airport], finish_airport_id: params[:finish_airport] ).where(date: target_date.beginning_of_day..target_date.end_of_day) else @flights = Flight.none # 首次加载时返回空集合,避免页面报错 end end
2. 修正日期选项的提交值
你之前生成@dates_options时,只把格式化后的字符串(比如02 May 22:21)作为选项值,这就丢失了年份和时区信息——数据库里的日期是带完整年份和时区的(比如Sat, 02 May 2020 22:21:00 UTC +00:00),用不完整的日期去查,肯定匹配不到。
上面的代码里,我们用date.iso8601作为选项的value,提交的参数会是类似2020-05-02T22:21:00Z的标准格式,既能被Rails正确解析,又能和数据库里的日期完美对应。
3. 表单代码不用改,直接用就行
你的表单代码没问题,select_tag会自动用上我们修正后的@dates_options,用户看到的还是友好的02 May 22:21格式,但提交的是完整的ISO日期参数。
额外提示:如果要精确匹配航班时间
如果你就是想查精确到分的某一班,那把查询逻辑改成精确匹配就行:
@flights = Flight.where( start_airport_id: params[:start_airport], finish_airport_id: params[:finish_airport], date: target_date )
现在再测试一下:提交表单后,URL里的date参数会变成标准ISO格式,controller能正确解析,再也不会报nil错误,而且能查到对应的航班啦~
内容的提问来源于stack exchange,提问作者user13138572
相关产品推荐
相关产品推荐

