Ruby on rails 如何使用Arel将表列引用为子句条件?

Ruby on rails 如何使用Arel将表列引用为子句条件?,ruby-on-rails,activerecord,arel,Ruby On Rails,Activerecord,Arel,我有这个范围: scope :in_range, lambda { |begin_time, end_time, excluded_sales = nil| where( 'start_at BETWEEN ? AND ? OR finish_at BETWEEN ? AND ? OR ? BETWEEN start_at AND finish_at OR ? BETWEEN start_at AND finish_at', begin_time, end_time, begin

我有这个范围:

scope :in_range, lambda { |begin_time, end_time, excluded_sales = nil|
  where(
    'start_at BETWEEN ? AND ? OR finish_at BETWEEN ? AND ? OR ? BETWEEN start_at AND finish_at OR ? BETWEEN start_at AND finish_at',
  begin_time, end_time, begin_time, end_time, begin_time, end_time)
  .where.not(id: excluded_sales)
}
这就产生了

> Sale.in_range(Time.now, Time.now + 1)
  Sale Load (0.6ms)  SELECT "sales".* FROM "sales"  WHERE (start_at BETWEEN '2014-12-12 10:45:47.065712' AND '2014-12-12 10:45:48.065714' OR finish_at BETWEEN '2014-12-12 10:45:47.065712' AND '2014-12-12 10:45:48.065714' OR '2014-12-12 10:45:47.065712' BETWEEN start_at AND finish_at OR '2014-12-12 10:45:48.065714' BETWEEN start_at AND finish_at) AND ("sales"."id" IS NOT NULL)
我需要使用Arel重写这个范围,因为我认为我不应该在这里使用原始SQL语法。 但我不知道如何在方法中使用表列引用。我尝试过此方法,但出现异常:

> s = Sale.arel_table
> begin_time = Time.now
> Sale.where(begin_time.in(s[:start_at]..s[:finish_at]))
  --> ArgumentError: bad value for range
我也试过这个,但运气不好:

> s = Sale.arel_table
> begin_time = Time.now
> Sale.where(begin_time.in('sales.start_time'..'sales.end_time')
  --> NoMethodError: undefined method `round' for "sales.end_time".."sales.start_time":Range
请告知如何将表格列作为Arel的条款条件

谢谢大家!

更新:

与OR语句相关的条件有四个:

开始时间在开始时间和结束时间的范围内 在开始时间和结束时间范围内完成 开始时间在开始时间和结束时间范围内 开始时间和结束时间范围内的结束时间 基本上,这只是一个日期范围重叠

我把它改写成

scope :in_range, lambda { |date_range, excluded_sales = nil|
  s = Sale.arel_table
  where(
    s.grouping(s[:starts_at].gteq(date_range.first).and(s[:starts_at].lteq(date_range.last)))
      .or(s.grouping(s[:ends_at].gteq(date_range.first).and(s[:ends_at].lteq(date_range.last))))
      .or(s.grouping(s[:starts_at].lteq(date_range.first).and(s[:ends_at].gteq(date_range.last))))
      .or(s.grouping(s[:starts_at].gteq(date_range.first).and(s[:ends_at].lteq(date_range.last))))
  ).where.not(id: excluded_sales)
}

也许有一种更简单的方法来实现我的目标?

据我所知,您希望选择所有记录,哪个范围与指定的记录相交?如果是这样,只需选择记录,这些记录的起始值在范围结束之前,而结束值在范围开始之后。因此,它应该是:

 scope :in_range, proc do |begin_time, end_time, excluded_sales|
    where(arel_table[:start_at].lteq(end_time)
     .and(arel_table[:finish_at].gteq(begin_time))
     .and(arel_table[:id].not_eq(excluded_sales)))
 end

请看一下我的更新问题-我已经为这个查询添加了可能的解决方案和条件。也许你可以复习一下?谢谢@蒂姆尔哈菲佐夫,蒂姆尔哈菲佐夫,蒂姆尔哈菲佐夫,蒂姆尔哈菲佐夫,蒂姆尔哈菲佐夫,蒂姆尔哈菲佐夫,蒂姆尔哈菲佐夫,蒂姆尔哈菲佐夫,蒂姆尔哈菲佐夫,蒂姆尔哈菲佐夫,蒂姆尔哈菲佐夫,蒂姆尔哈菲佐夫,蒂姆,蒂姆尔哈菲佐夫,蒂姆,蒂姆,蒂姆尔哈菲佐夫,蒂姆,蒂姆,蒂姆,蒂姆,蒂姆,蒂姆,蒂姆尔哈菲佐夫,蒂姆,蒂姆,蒂姆,蒂姆,蒂姆,蒂姆尔哈菲佐夫,蒂姆,蒂姆,蒂姆,蒂姆,蒂姆,蒂姆,蒂姆,蒂姆,蒂姆,蒂姆,蒂姆,蒂姆,蒂姆,蒂姆,蒂姆,蒂姆,蒂姆,蒂姆,蒂姆,蒂姆,蒂姆,蒂姆,蒂姆,蒂。非常感谢。