微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ruby-on-rails – 我该怎么做? Model.where(“created_at> =#{Time.now – 5.days}”)

这一直在欺骗我一段时间…

如何在Rails ActiveRecord查询中字符串插入datetime?

# Works,but supeh ugleh:
Model.where("created_at >= ?",Time.Now - 5.days)

# How do I do this?
Model.where("created_at >= #{Time.Now - 5.days}")
# As is,it produces the following error message:
# ActiveRecord::StatementInvalid: PG::Error: ERROR:  Syntax error at or near ...

我关心的是代码可读性的原因:

# I like this better:
Model.where("created_at >= #{Time.Now - 5.days} OR" + \
            "updated_at >= #{Time.Now - 3.days}")

# than this:
Model.where("created_at >= ? OR updated_at >= ?",Time.Now - 5.days,Time.Now - 3.days)

解决方法

我建议不要使用字符串插值,有很多锋利的边缘,你可能会有更多的乐趣摆动苹果在一桶鱼钩.你应该这样做:
Model.where(
    'created_at >= :five_days_ago or updated_at >= :three_days_ago',:five_days_ago  => Time.Now - 5.days,:three_days_ago => Time.Now - 3.days
)

使用(well)命名的占位符为您提供了您认为字符串插值提供的可读性和位置独立性,但很好地回避了引用,时区和格式问题,您可以对字符串进行插值.

但是如何安全地使用字符串插值?有一些事情你必须自己处理:

>引用和转义.
>时间戳格式
>也许是时区.

ActiveRecord将为您处理所有这些废话.

不要尝试引用自己的话,用司机的引用方法.您可以访问connection.quote以正确引用字符串.

任何数据库都将知道如何处理ISO 8601 timestamps,并有一个方便的iso8601方法. ISO 8601也方便地包括时区,数据库应该能够解析(但是如果不能,那么你必须用.utc手工将你的时间转换成UTC).

所以,要安全:

Model.where("created_at >= #{connection.quote((Time.Now - 5.days).utc.iso8601)} " + \
         "OR updated_at >= #{connection.quote((Time.Now - 3.days).utc.iso8601)}")

现在不是很漂亮吗?使用ISO 8601时间戳,您应该安全地用简单的单引号代替connection.quote调用

Model.where("created_at >= '#{(Time.Now - 5.days).utc.iso8601}' " + \
         "OR updated_at >= '#{(Time.Now - 3.days).utc.iso8601}'")

但你仍然会有很多的噪音和丑陋,你会发展不好的习惯.

在1999年,我们不像PHP程序员那样派对,所以不要在sql中使用字符串插值来使用命名占位符,来放弃虚假的懒惰.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐