#activerecord #timezone
#activerecord #Часовой пояс
Вопрос:
Я прочитал довольно много статей, сделал свою домашнюю работу. У меня все времена сохранены как UTC, каждый пользователь устанавливает свой собственный часовой пояс и т.д. Вот проблема, с которой я сталкиваюсь:
Time.zone
=> GMT-05:00 Eastern Time US Canada
t = Ticket.first
t.hold_until = "Jan 1, 2012 9:00PM"
t.save!
t.hold_until
=> Sun, 01 Jan 2012 16:00:00 EST -05:00
# notice the above time lost 5 hours
Проблема в том, что строка взята из POST-запроса, предоставленного пользователем. Не разумнее ли предположить, что пользовательский ввод осуществляется по их местному времени, а не по UTC. Я что-то упускаю или это не должно быть значением ActiveRecord по умолчанию? Каков правильный способ сделать это, помимо необходимости конвертировать время во всех моих контроллерах. Это просто кажется неправильным и не очень СУХИМ.
Ответ №1:
Я разобрался с проблемой, и она связана с плохо написанным кодом в ActiveRecord (сюрприз!). В любом случае, ActiveRecord::Base.define_attribute_methods вызывается лениво из-за отсутствия метода. У меня этот метод был определен следующим образом:
def hold_until=(value)
# do some stuff here
super
end
Итак, ActiveRecord пропускал этот метод, думая, что он был определен. Это не должно иметь значения, но из-за плохого дизайна это имеет значение. В AR есть множество различных способов определения методов на основе их типа столбца. Вызов super side выполняет это и переходит прямо к общему вызову «write_attribute». Единственное решение — преобразовать время самостоятельно. Вы не можете вызвать define_attribute_methods перед включением модулей из-за всей этой ерунды с alias_method_chain. И вы не можете использовать код, который они уже написали, потому что он находится в блоке class_eval. Я бы рекомендовал datamapper, если это вообще возможно.