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中使用字符串插值来使用命名占位符,来放弃虚假的懒惰.

相关文章

validates:conclusion,:presence=>true,:inclusion=>{...
一、redis集群搭建redis3.0以前,提供了Sentinel工具来监控各...
分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣...
上一篇博文 ruby传参之引用类型 里边定义了一个方法名 mo...
一编程与编程语言 什么是编程语言? 能够被计算机所识别的表...
Ruby类和对象Ruby是一种完美的面向对象编程语言。面向对象编...