I have an edit view for an Event
model with name
, start_time
, and end_time
fields. My view is a form that looks roughly like this:
# ...
# form with:
# - event name
# - datetime_select for event start_time (in business's local time zone)
# - datetime_select for event end_time (in business's local time zone)
Now, here's the problem: the start_time
and end_time
has a time zone attached to it, but that time is lost when we render the view, because the datetime_select doesn't include a field for time zone. The result is that we have a "UTC time" which is actually the local time stripped of its timezone.
To recap, the situation looks like this when we render the form in the view, then immediately submit it without making any changes:
db time: 2011-05-15 @ 1100 UTC
converted to local time: 2011-05-15 @ 0600 CDT
time stored in view: 2011-05-15 @ 0600 UTC (time zone info lost)
time posted back to db: 2011-05-15 @ 0600 UTC
Notice that the time that was stored was 1100 UTC originally but is now 0600 UTC, even though we didn't make any changes. That's a serious error.
There's a number of approaches we could take here. What's the smartest way to avoid losing the time开发者_如何学运维 zones when posting to the view? (Note that the model might get updated in ways other than posting the form -- e.g., through an API.)
It never feels very satisfactory but i usually deal with this by making a couple of new methods for a virtual attribute called local_time, or time_formatted or something like that, which convert back and forth from the UTC time that is stored in the db.
In this example the db field is "deadline" and the virtual attribute is "deadline_formatted":
def deadline_formatted
self.deadline
end
def deadline_formatted= s
self.deadline = s
end
Then, in the form,
<%= f.label :deadline_formatted, "Deadline" %>
<%= f.text_field :deadline_formatted %>
Via some rails magic, which i still don't quite understand*, this is enough to do it - it looks like it shouldn't work but it does. At least it did for me.
*the part that i don't understand is that setting the deadline field in the form will go on to call the deadline= method with the value from the text field. Instead, i call the deadline_formatted= method, which just passes the result to deadline=, so you'd think the result would be identical. But, somehow, the time is translated to and fro from UTC (database) to local time (form).
you could try to use the delocalize gem: https://github.com/clemens/delocalize
精彩评论