在 Rails 中,如何编写一个带有“where”的查找器来比较两个日期?

Posted

技术标签:

【中文标题】在 Rails 中,如何编写一个带有“where”的查找器来比较两个日期?【英文标题】:In Rails, how do you write a finder with "where" that compares two dates? 【发布时间】:2021-12-26 23:30:13 【问题描述】:

我使用的是 Rails 4.2。我有一个具有这些日期时间属性的模型

submitted_at
created_at

如何编写一个查找器方法来返回所有模型,其中提交的字段按时间顺序出现在 created_at 字段之前?我试过这个

MyModel.where(:submitted_at < :created_at)

但这会返回我数据库中的所有内容,甚至是不匹配的项目。

【问题讨论】:

为什么 submit_at 会在 created_at 之前发生?通常 created_at 是保存记录时自动设置的时间戳 隐藏着巨大的奥秘 MyModel.where(MyModel.arel_table[:submitted_at].lt(MyModel.arel_table[:created_at]))。我也可以看到很多次提交可能早于创建,例如在这些情况下,手动输入、数据轮询、导入等数据在系统中创建之前绝对可以以某种其他形式存在。 @engineersmnky 我可能会早于 created_at 但是,IMO 这很令人困惑。即使您手动导入,我会说它们应该......相等。 @razvans 非常好,但如果我今天给你发一份文件,那么我今天就提交了。如果你直到下周才导入它,我提交它时它不会改变。我帮助创建了多个执行批处理的系统,其中文件的处理出于计时目的而延迟,但实际提交日期和时间为后代保留,因此“提交日期”总是早于自动填充的 created_at 【参考方案1】:

where(:submitted_at &lt; :created_at) 实际上是where(false)。当您将两个符号与 lt/gt 运算符进行比较时,您实际上只是在按字母顺序比较它们:

:a < :b # true
:c > :b # true

where(false) 或blank? 的任何其他参数只返回一个“无作用域”的链接关系。

ActiveRecord 查询界面实际上并没有直接的方法来比较这样的列。

您可以使用 SQL 字符串:

Resource.where('resources.submitted_at < resources.created_at')

或者使用 Arel 创建查询:

r = Resource.arel_table
Resource.where(r[:submitted_at].lt(r[:created_at]))

结果完全相同,但 Arel 解决方案可以说更具可移植性,并且避免了对表名进行硬编码(或创建模棱两可的查询)。

【讨论】:

【参考方案2】:

您可以使用.to_sql 查看生成了什么查询。

对于你来说,它看起来像这样:

Resource.where(:submitted_at < :created_at).to_sql 
# => SELECT `resources`.* FROM `resources`

如果你像下面这样更新,你会得到一些结果:

Resource.where('submitted_at < created_at')
# => SELECT * FROM `resources` WHERE (submitted_at < created_at)

【讨论】:

这会打印出 sql 但您如何在 Rails 控制台中实际打印出结果? 如果你打算在一个范围内使用它,那么在没有指定表名的情况下使用created_at 势必会导致一个模棱两可的查询,因为它在一般的 Rails 应用程序中的几乎每个表上。 已更新。只需删除.to_sql,只是为了看看它是否有效。可以加.count.first @max 如果你加入,你是对的。 嗯,编写范围时的经验法则是,您不知道以后将如何使用它。具体一点。

以上是关于在 Rails 中,如何编写一个带有“where”的查找器来比较两个日期?的主要内容,如果未能解决你的问题,请参考以下文章

如何在带有 squeel 的 Rails 中使用连接

Rails - 如何编写一个链接,该链接将被调用以在控制器中调用带有参数的操作?

如何在 WHERE 子句中编写带有 SELECT 语句的 SQL DELETE 语句?

Rails 5范围问题

如何在 ruby​​ on rails 中编写嵌套查询?

如何编写带有子查询的 Django 查询作为 WHERE 子句的一部分?