Ответ 1
Мощность Squeel FTW!!! Я уверен, вам понравится.
$gem install squeel
model.rb
Model.where{date_colum > 10.years.ago & date_column < DateTime.now}
Я создаю систему, которая должна быть уверена, что запланированные "поездки" не пройдут на коленях. Для этого я пытаюсь проверить start_date и end_date, чтобы убедиться, что они не находятся в датах начала и окончания другой поездки.
class TripdateValidator < ActiveModel::EachValidator
def validate_each(object, attribute, value)
# Check value exists as end_date is optional
if value != nil
parsed_date = Date.parse(value)
# is the start date within the range of anything in the db
trips = Trip.where(['start_date >= ? AND end_date <= ? AND user_id = ?', parsed_date, parsed_date, object.user_id])
# overlapping other trips, aghhh
object.errors[attribute] << 'oh crap' if trips
end
end
end
Дата исходит из поля type = "date", которое работает от jQuery UI Datepicker и содержит формат 2011-01-01. Это доходит до рельсов как 2011-01-30 00:00:00 UTC, которые я не совсем понимаю.
Если я попытаюсь использовать Date.parse() для этого значения, он даст ошибку:
TypeError в TripsController # create
$_ значение должно быть String (задано nil)
Rails.root:
/Users/phil/Sites/travlrapp.com
Трассировка приложения | Рамочная трасса | Полная трассировкаприложение/модели/trip.rb: 29: в
validate_each'
создать "
app/controllers/trips_controller.rb:75:in
приложение/контроллеры/trips_controller.rb: 74: в
`create '
Всякий раз, когда я запускаю запрос, ничего не возвращается. Может ли это быть проблемой формата даты, моя логика сломана, или я делаю что-то действительно глупое? Застрял на этом некоторое время, а google не помогает.
Изменить Люди фокусируются на ошибке Date.parse, но это не основная проблема. Где я застрял в том, что я не понимаю, как делать сравнения дат, когда все находится в совершенно разных форматах.
Я заменил Date.parse() для Chronic.parse(), и теперь я получаю следующие SQL-запросы:
SELECT "trips".* FROM "trips" WHERE (start_date >= '2011-01-26 00:00:00.000000' AND end_date <= '2011-01-26 00:00:00.000000' AND user_id = 19)
Это ничего не возвращает. Датами, которые я тестирую, являются:
начало: 2011-02-17 00: 00: 00.000000 конец: 2011-02-21 00: 00: 00.000000
Видя, как я думаю, даты отформатированы правильно, теперь это больше похоже на логическую проблему. Как я могу проверить пару совпадающих дат > .
Мощность Squeel FTW!!! Я уверен, вам понравится.
$gem install squeel
model.rb
Model.where{date_colum > 10.years.ago & date_column < DateTime.now}
Я отвечаю на ваше редактирование, в основном, и думаю, что вы не получаете никаких результатов по двум причинам:
Во-первых: Я подозреваю, что ваш парсер предоставляет вам объекты DateTime, в то время как вам просто нужны простые объекты Date. Передайте генератор запросов SQL в Rails и введите строку 'YYYY-MM-DD hh.mm.ss.uuu...'
, тогда как в базе данных будет просто строка 'YYYY-MM-DD'
для сравнения столбцов даты; синтаксический анализатор даты не работает, возвращает NULL, все сравнения с ошибкой NULL и т.д., и вы возвращаете пустой набор результатов.
Измените parsed_date
на parsed_date.to_date
, и вы должны быть в порядке на этом фронте.
Второе: взгляните на свой SQL, этот фрагмент, в частности, start_date >= ? AND end_date <= ?
. Мне кажется, что он обнаружит только столкновение, если в ходе поездки вы проверяете дату начала, которая позднее даты окончания.
Итак, попробуйте start_date <= ? AND end_date >= ?
или ? BETWEEN start_date AND end_date
, который я лично предпочитаю, так как он немного читаем.
Надеюсь, это поможет!
Для проверки перекрытия вы можете попробовать один из этих камней https://github.com/chrisb87/range_validator или https://github.com/robinbortlik/validates_overlap
Для тех, кто приземлился здесь, проверьте Rails guide в условиях Range:
Client.where(created_at: (Time.now.midnight - 1.day)..Time.now.midnight)
Это создаст следующий SQL:
SELECT * FROM clients WHERE (clients.created_at BETWEEN '2008-12-21 00:00:00' AND '2008-12-22 00:00:00')
Таким образом, вы можете искать поля между двумя датами, используя диапазон.
Я предпочитаю:
Model.where{date_colum >> (10.years.ago..Datetime.now)}
Пробовали ли вы с классом TimeZone
:
parsed_date = Time.zone.parse(value)
Здесь docs:
http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html#method-i-parse
Я бы записал "значение" и посмотрел, удален ли он от того, что может обрабатывать Date.parse(). Если он выглядит разборчивым, посмотрите, работает ли Date.parse на нем в irb, и если да, проверьте его в консоли env (./ script/console или rails c) для вашего приложения. Это должно выявить проблему.
Как насчет этого?
overlaps = Trip.where(
"(DATEDIFF(start_date, ?) * DATEDIFF(?, end_date)) >= 0",
self.end_date,
self.start_date
)
В основном это говорит:
Если каждая дата начала смотрит на другую дату окончания, они выглядят в том же направлении? Затем они перекрываются.
Вы можете использовать метод обложки
он возвращает true, если данные между выбранным диапазоном в противном случае false