避免在 Rails 视图中丢失时区的最佳方法是什么?



我有一个Event模型的编辑视图,其中包含namestart_timeend_time字段。我的观点是一个大致看起来像这样的形式:

# ...
# 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)

现在,问题来了:start_timeend_time附加了一个时区,但是当我们渲染视图时,该时间会丢失,因为datetime_select不包含时区字段。结果是,我们有一个"UTC时间",它实际上是从其时区中剥离的本地时间。

回顾一下,当我们在视图中呈现表单时,情况如下所示,然后立即提交而不进行任何更改:

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

请注意,存储的时间最初是 1100 UTC,但现在是 0600 UTC,即使我们没有进行任何更改。这是一个严重的错误。

我们可以在这里采取多种方法。在发布到视图时避免丢失时区的最聪明方法是什么?(请注意,模型可能会以发布表单以外的方式进行更新 - 例如,通过 API。

感觉从来都不是很令人满意,但我通常通过为名为 local_time 或 time_formatted 或类似内容的虚拟属性制作一些新方法来解决这个问题,这些方法从存储在数据库中的 UTC 时间来回转换。

在此示例中,db 字段为"deadline",虚拟属性为"deadline_formatted":

def deadline_formatted
  self.deadline
end
def deadline_formatted= s
  self.deadline = s
end

然后,在表格中,

<%= f.label :deadline_formatted, "Deadline" %>
<%= f.text_field :deadline_formatted %>

通过一些我仍然不太理解的轨道魔法*,这足以做到这一点 - 看起来它不应该工作,但它确实有效。 至少它对我有用。

*我不明白的部分是,在表单中设置截止日期字段将继续使用文本字段中的值调用 deadline= 方法。 相反,我调用 deadline_formatted= 方法,它只是将结果传递给 deadline=,所以你会认为结果是相同的。 但是,不知何故,时间从UTC(数据库)到本地时间(表单)来回转换。

您可以尝试使用去本地化 gem: https://github.com/clemens/delocalize

相关内容

  • 没有找到相关文章

最新更新