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 默认值?除了必须转换我所有控制器中的时间之外,执行此操作的正确方法是什么?这似乎是错误的,而且不是很干。
I've read quite a few articles, done my homework. I have all times stored as UTC, each user sets their own time zone, etc. Here's the problem I'm having:
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
The issue is that the string is from a POST request supplied by the user. Doesn't it make the most sense to assume user input is in their local time, not UTC. Am I missing something or shouldn't that be the ActiveRecord default? Whats the proper way to do this, beyond having to convert the time in all of my controllers. That just seems wrong and not very DRY.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我发现了这个问题,它与 ActiveRecord 中编写得不好的代码有关(惊讶!)。无论如何,ActiveRecord::Base.define_attribute_methods 通过方法缺失被延迟调用。我这样定义了这个方法:
因此 ActiveRecord 会跳过该方法,认为它已定义。这应该不重要,但由于设计不佳,它确实如此。 AR 有多种不同的方式来根据列类型定义方法。调用 super side 会执行此操作并直接进行一般的“write_attribute”调用。唯一的解决办法就是自己转换时间。由于所有alias_method_chain的废话,在包含模块之前你不能调用define_attribute_methods。而且您无法利用他们已经编写的代码,因为它位于 class_eval 块中。如果可能的话,我会推荐 datamapper。
I figured out the issue and it has to do with poorly written code within ActiveRecord (surprise!). Anyways, ActiveRecord::Base.define_attribute_methods gets called lazily via method missing. I had this method defined like so:
So ActiveRecord was skipping that method thinking it was defined. It shouldn't matter, but due to poor design it does. AR has a variety of different ways to define methods based on their column type. Calling super side steps this and goes right to a general "write_attribute" call. The only solution is to convert the time yourself. You can't call define_attribute_methods before you include the modules because of all the alias_method_chain bullshit. And you can't leverage the code they've already written because its in a class_eval block. I would recommend datamapper if at all possible.