У меня есть этот объем:Как передать столбец таблицы как условие условия с 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_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 здесь. Но я не знаю, как использовать метод in
с ссылкой на столбец. Я пробовал это, но есть исключение:
> 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
утверждением:
start_at
в диапазонеbegin_time
иend_time
finish_at
в диапазонеbegin_time
иend_time
begin_time
я п диапазонstart_time
иfinish_time
end_time
в диапазонеstart_time
иfinish_time
В основном это просто дата диапазоны перекрываются.
я переписал его
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)
}
Может быть, есть способ проще достичь своей цели?
Пожалуйста, взгляните на мой вопрос с обновлением - я добавил возможные варианты и условия для этого запроса. Может быть, вы можете просмотреть его? Благодаря! –
@TimurKhafizov на самом деле ваш вариант правильный, но моего достаточно, и он проще, я когда то вычислял как правильно и оптимально считать пересечения диапазонов. –
Да, все мои тесты проходят, поэтому это лучшее решение. Спасибо! –