Среда: Rails 2.2.2, Oracle 10g
Большинство столбцов, объявленных "date" в моих моделях ActiveRecord, являются именно такими: date: они вообще не заботятся о времени.
Итак, с моделью, объявленной таким образом: #
class MyDateOnlyModel < ActiveRecord::Migration
def self.up
create_table :my_date_only_model do |t|
t.date :effective_date
t.timestamps
end
end
end
написать такой тест:
test_date = Date.new(2008,12,05)
MyDateOnlyModel.create!(:effective_date => test_date)
assert_equal test_date, MyDateOnlyModel.find(:first).effective_date
должно пройти, не так ли? (Если, конечно, я ничего не испортил, расшифровывая вышеизложенное)
Но это не совсем так. Я получаю это:
<Fri, 05 Dec 2008> expected but was
<Fri, 05 Dec 2008 00:00:00 UTC +00:00>.
Итак, я ввел дату в базу данных и получил ... ну, что я получаю сделал?
puts MyDateOnlyModel.find(:first).eff_date.class
говорит, что у меня действительно есть ActiveSupport::TimeWithZone. Это было совсем не то, чего я хотел.
Есть ли простой способ сообщить ActiveRecord, что некоторые (не все) столбцы являются Date и только Date?
ОБНОВЛЕНИЕ: больше жалоб ...
Да, я мог бы использовать to_date:
assert_equal test_date, MyDateOnlyModel.find(:first).effective_date.to_date
работает отлично. Но этого я пытаюсь избежать. Я попросил АР назначить мне свидание, я хочу свидание еще раз.
И я мог бы добавить в свой класс метод effective_date_as_date - он тоже работает. Но, конечно, не невозможно просто устроить свидание, дагнаббит.
ПРЕДВАРИТЕЛЬНОЕ ОБНОВЛЕНИЕ
В конце концов я понял, почему это была особая проблема с Oracle: нет различия между DATE и DATETIME, поэтому ActiveRecord не может без посторонней помощи определить, означает ли нулевое время полночь (возможно, с поправками часового пояса) или только дату. Ба. Глупый оракул. Так что мне придется либо пойти по пути плагина, либо изменить мою базу данных (заманчиво, очень заманчиво), либо продолжить беспорядок to_date / to_time, который у меня есть в настоящее время.





Вы пробовали преобразовать свой атрибут в тип даты?
API описывает to_date следующим образом:
Converts self to a Ruby Date object; time portion is discarded
test_date = Date.new(2008,12,05)
MyDateOnlyModel.create!(:effective_date => test_date)
assert_equal test_date, MyDateOnlyModel.find(:first).effective_date.to_date
Обновлять:
Похоже, у этого адаптера есть решение вашей проблемы ...
Set the option below and as a result columns with DATE in their name will be emulated as Date (and not as Time which is default for DATE columns in database)
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
да. И фу. На самом деле, черт возьми. Я специально пытаюсь избежать написания to_date во всем моем коде. СУХОЙ и все такое ... Я мог бы переопределить аксессуар в моих моделях, где это необходимо, но снова фу.
Какую базу данных вы используете? Возможно, тип столбца, с которым сопоставляется объект Date, не соответствует тому, что вы думаете в своей базе данных. Очень сомнительно, но возможно.
Oracle: это столбец DATE, который также может принимать значение времени. Кажется, я чрезмерно страдаю от даты и времени независимо от БД, что заставляет меня думать, что я чего-то упускаю ... :)
Вы пробовали Enhanced Oracle Adapter for ActiveRecord? Раньше я использовал Rails с Oracle, и это интересное сочетание. Похоже, это может решить вашу проблему! См. Мой ответ по ссылке.
Месяцы спустя: я использую усовершенствованный Oracle, и мне это нравится.
Я обнаружил ошибку: нельзя сравнивать TimWithZone с Date. «Сравнение неуместно, - говорит мне Рубин.
Вы абсолютно правы: вот почему происходит вся эта ужасная ерунда to_date / to_time. Я просто не могу поверить, что я единственный, кто чувствует боль, и не похоже, чтобы она не была устранена. Но, возможно, я ошибаюсь.
На самом деле это не ответ (и поэтому я просто оставляю это в качестве комментария!), Но я хотел бы отметить, что ORM DataMapper поддерживает этот случай, требуя, чтобы все свойства были объявлены (с типами) в модели.