代码之家  ›  专栏  ›  技术社区  ›  daveanderson88

使用.where on instance方法搜索日期范围

  •  0
  • daveanderson88  · 技术社区  · 7 年前

    我有一个模型(称为运行),这里有两个实例来显示它是什么样子的:

    <Run id: 138, route_id: 1, leave_date: "2018-07-17 08:00:00", left: false, returned: false, created_at: "2018-07-17 14:08:28", updated_at: "2018-07-17 14:08:28", distance: nil, transport_time: nil>
    <Run id: 139, route_id: 1, leave_date: "2018-07-18 09:00:00", left: false, returned: false, created_at: "2018-07-17 14:08:28", updated_at: "2018-07-17 14:08:28", distance: nil, transport_time: nil>
    

    运行模型上有一个实例方法(在run.rb中)

      def delivery_date
        (route.delivery_working_day_offset.to_i).business_days.after(leave_date)
      end
    

    它提供日期时间,例如:

    Run.first.delivery_date
    

    退货

    Tue, 17 Jul 2018 09:00:00 UTC +00:00
    

    我要选择日期与某个日期匹配的运行,如果可能,请使用.where。通常我会使用如下的方法,但它只对模型的属性(如leave_date)起作用,而对实例方法(如delivery_date)不起作用:

    Run.where('delivery_date BETWEEN ? AND ?', date.beginning_of_day, date.end_of_day)
    

    如何执行此选择? 非常感谢。

    3 回复  |  直到 7 年前
        1
  •  0
  •   Martin    7 年前

    您可以使用Select方法:

    Run.all.select { |r| r.delivery_date.in?(date.beginning_of_day..date.end_of_day) }
    

    但是如果你有很多次跑步的话效率就不高了。

    我建议将交货日期数据保存在名为 delivery_date 对数据库端的记录进行过滤:

    Run.where(delivery_date: date.beginning_of_day..date.end_of_day)
    
        2
  •  0
  •   Hubert Jakubiak    7 年前
    Run.all.select { |r| (date.beginning_of_day..date.end_of_day).include?(r.delivery_date) }
    
        3
  •  0
  •   Leo    7 年前

    没有机会从数据库查询中调用Ruby方法。而且,这没有任何原因,因为看起来和Ruby迭代一样。但是,您可以在数据库查询中为Ruby方法编写一个简单的类似函数。 尝试如下操作:

    Run.joins(:routes)
       .where("runs.leave_date + interval '1 day' * routes.delivery_working_day_offset BETWEEN ? AND ?', 
              date.beginning_of_day, date.end_of_day)
    

    这个例子忽略了周末和工作日之间的区别。但是有太多的例子说明如何在数据库查询中编写工作日函数。

    最简单的解决方案:将交货日期保存到其中一个数据库表中。