Рельсы Даты Время и расписание - PullRequest
11 голосов
/ 04 декабря 2010

У меня было следующее приспособление:

link_1:
  user: tom
  image: boy1
  created_at: <%= 5.day.ago %>

Я попробовал следующий запрос:

Links.where("Date(created_at) = ?", 5.day.ago.to_date)

Ответ:

[]

Grrrr .... печатает ... печатает ... царапины ... Я наконец попробовал:

link_1:
  user: tom
  image: boy1
  created_at: <%= 5.day.ago.to_date %>

и

Links.where("Date(created_at) = ?", 5.day.ago.to_date)

наконец-то отвечает

[#<Link id: 298486374, user_id: 1038054164, image_id: 482586125, created_at: "2010-11-28 00:00:00", updated_at: "2010-12-03 21:32:19">]

Чего я ожидал, но зачем мне было ставить to_date? Мне это не понятно, потому что когда я создаю объект без указания даты создания, я могу выбрать его с помощью следующего выражения where без вопроса:

Links.where("Date(created_at) = ?", Date.today)

Есть идеи?

Ответы [ 4 ]

20 голосов
/ 04 декабря 2010

В приборах у вас должно быть:

created_at: <%= 5.day.ago.to_s(:db) %>

Ваш запрос будет:

Links.where("created_at = ?", ...

Позвольте ActiveRecord позаботиться о деталях перемещения данных из базы данных и в нее.Мы используем ORM по причине.

Ссылка .

1 голос
/ 28 августа 2014

created_at - это поле DateTime, а 5.days.ago эффективно возвращает объект DateTime. Для этого объекта будет установлено то же время, что и в момент его вызова, например. Суббота, 23 августа 2014 10: 30: 37 , и это то, что помещается в базу данных.

В случае неудачи, когда вы снова позвоните 5.days.ago (даже в том же исполнении), новое время, скорее всего, будет другим, например. Суббота, 23 августа 2014 г. 10:30: 38 . Поэтому вы можете видеть, что они не равны, и вы не получите совпадений.

Когда вы добавляете .to_date, вы получаете объект Date, который не имеет временной составляющей. Когда это сохраняется в базе данных или используется в вашем запросе, оно всегда будет иметь время 00:00:00 (полночь). Следовательно, дата и время будут совпадать (если вы не пытаетесь запустить приборы и выполнять запросы ровно в полночь)

1 голос
/ 04 декабря 2010

Я бы предположил, что это из-за разницы во времени между созданием прибора и вызовом запроса.

5 дней назад + 0,00025 мс> 5 дней назад

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

0 голосов
/ 04 декабря 2010

Разница между вашими двумя делами заключается в том, что при вызове to_date вы теряете значение времени, поэтому конечным результатом является отметка времени created_at, установленная на полночь этого дня. Вы также избегаете перевода часового пояса с TimeWithZone. Честно говоря, у нас нет достаточно информации, чтобы предположить, что происходит за этим. Чтобы точно увидеть, что происходит, лучше всего посмотреть на запросы в вашем log/test.log - если вы не видите запросов, вы можете включить их, установив log_level в :debug в config/environments/test.rb. Не стесняйтесь копировать и вставлять запросы SQL здесь.

@ Ibz также поднимает хороший вопрос: использование .to_s(:db) является хорошей идеей, поскольку файл фиксации ERB оценивается как строка, а затем читается как YAML, что может вызвать некоторые проблемы с приведением значений к строкам. Использование .to_s(:db) решит эту проблему, но чтобы избежать этого в будущем (и получит кучу дополнительных функций), я бы рекомендовал использовать factory_girl вместо приборов.

Подобные проблемы распространены при работе с датами тестирования, особенно если вы пытаетесь выполнить запрос по равенству двух дат или временных отметок. Чтобы решить эти проблемы, я рекомендую либо выбирать произвольные фиксированные даты / время в прошлом, чем делать 5.days.ago, либо, если вам нужно использовать динамические даты / время, использовать гем Timecop для управления / замораживания время в ваших тестах.

...