使用.where on实例方法进行日期范围搜索

时间:2018-07-17 14:37:55

标签: ruby-on-rails ruby activerecord

我有一个模型(称为Runs),这里有2个实例以显示其外观:

<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模型上有一个实例方法(在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 个答案:

答案 0 :(得分:0)

您可以使用选择方法:

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)

答案 1 :(得分:0)

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

答案 2 :(得分:0)

没有机会从数据库查询中调用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)

该示例忽略了周末和工作日之间的区别。但是有太多关于如何在数据库查询中编写business_days函数的示例。

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