Rails - это дата между двумя датами? - PullRequest
13 голосов
/ 23 января 2011

Я создаю систему, которая должна обеспечить, чтобы запланированные «поездки» не пересекались.Для этого я пытаюсь проверить дату начала и окончания, чтобы убедиться, что они не входят в даты начала и окончания другой поездки.

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 (не указано)

Rails.root:
/ Users / phil / Sites / travlrapp.com
Трассировка приложений |Framework Trace |
Full Trace

app / models / trip.rb: 29: в
validate_each'<br> app/controllers/trips_controller.rb:75:in создать '
app / controllers / 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

Видя, как я думаю, датытеперь правильно отформатирован, это больше похоже на проблему логики.Как, черт возьми, я могу проверить перекрывающиеся даты>.

Ответы [ 9 ]

10 голосов
/ 05 июня 2012

Squeel power FTW !!! Я уверен, вам понравится

$ gem install squeel

model.rb

Model.where{date_colum > 10.years.ago & date_column < DateTime.now}
3 голосов
/ 19 сентября 2014

Для тех, кто приземлится здесь, проверьте Направляющие рельсы в Условиях диапазона:

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')

Итак, выможно искать поля между двумя датами, используя диапазон.

3 голосов
/ 22 апреля 2011

Для проверки перекрытия вы можете попробовать один из этих драгоценных камней https://github.com/chrisb87/range_validator или https://github.com/robinbortlik/validates_overlap

3 голосов
/ 27 января 2011

В основном я отвечаю на ваши изменения и думаю, что вы не получаете никаких результатов по двум причинам:

Во-первых: я подозреваю, что ваш синтаксический анализатор предоставляет вам объекты DateTime, в то время как вам действительно нужны простые объекты Date. Передайте DateTime в генератор 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, который я лично предпочитаю, так как он немного более читабелен.

Надеюсь, это поможет!

2 голосов
/ 08 октября 2013

Я предпочитаю:

Model.where{date_colum >> (10.years.ago..Datetime.now)}
0 голосов
/ 24 декабря 2014

Вы можете использовать метод покрытия

, он возвращает истину, если данные между выбранным диапазоном в противном случае ложь

0 голосов
/ 25 января 2013

Как насчет этого?

overlaps = Trip.where(
    "(DATEDIFF(start_date, ?) * DATEDIFF(?, end_date)) >= 0",
    self.end_date,
    self.start_date
)

Это в основном говорит следующее:

Если каждая дата начала смотрит на дату окончания другого, они смотрят в том же направлении?Тогда они перекрываются.

0 голосов
/ 24 января 2011

Я бы записал «значение» и увидел бы, близко ли оно к чему-то, что может обработать Date.parse (). Если это выглядит как parsable, посмотрите, работает ли Date.parse с ним в irb, и если это так, проверьте его в консоли env (./script/console или rails c) для вашего приложения. Это должно отследить проблему.

0 голосов
/ 23 января 2011

Вы пробовали с TimeZone классом:

parsed_date = Time.zone.parse(value)

Вот документы:

http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html#method-i-parse

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...