将日期范围参数传递给Rails中的SQL / ActiveRecord查询

时间:2016-02-22 12:35:45

标签: sql ruby-on-rails ruby ruby-on-rails-4 activerecord

这里我有一个Order和一个OrderReport表。我正在进行连接,从每个表中提取一些数据。

 OrderReport.joins("INNER JOIN orders on orders.id = order_reports.for_object_id and order_reports.for_object_type = 'Order'").

group("order_reports.sales_user_id, EXTRACT(MONTH from event_at), orders.user_id,event_at").

pluck("order_reports.sales_user_id, EXTRACT(MONTH from event_at), orders.user_id,sum((cached_user_total_due - cached_sales_tax) * split_percentage), min(event_at)")

我有这么长的sql + ActiveRecord查询。我想添加一个初始化程序,并让它在日期开始和日期结束时使其更灵活,以便能够从前一年开始提取报告。

开始日期和结束日期将来自具有event_at列的Order表。我知道我会从这开始:

  attr_reader :start_date, :end_date

  def initialize(start_date:, end_date:)
    @start_date = start_date
    @end_date = end_date 
  end

2 个答案:

答案 0 :(得分:2)

您可以通过定义这样的范围来实现此目的:

class OrderReport < ActiveRecord::Base
  scope :during, -> (start, end) {
    where('event_at >= ? AND event_at <=?', start, end)
  }
end

然后,您可以轻松地进行查询:

OrderReport.during(start_date, end_date).joins(pla pla pla)

答案 1 :(得分:2)

您可以通过以下方式使用范围对象来使用ActiveRecord接口的范围:

class OrderReport
  scope :for, -> (begins, ends) { where(event_at: begins..ends) }
end

您可以使用传递Date对象或字符串参数,如:

# with strings
OrderReport.for("2015-12-12", "2015-12-30")

# with date objects
begins = Date.new(2015, 12, 12)
ends   = Date.new(2015, 12, 30)
OrderReport.for(begins, ends)

这将产生一个如下所示的SQL查询:

SELECT * FROM 
  order_reports
WHERE
  order_reports.event_at BETWEEN '2015-12-12' AND '2015-12-30'

这样您就可以让Arel处理查询构建,而不必担心SQL适配器的可配置性。