ruby-on-rails Rails:如何在.select()请求中使用.to_sql

rjzwgtxy  于 2022-11-19  发布在  Ruby
关注(0)|答案(2)|浏览(87)

我有一个ActiveRecord请求:

Post.all.select { |p| Date.today < p.created_at.weeks_since(2) }

我希望能够使用.to_sql查看它生成了什么SQL请求
我得到的错误是:NoMethodError: undefined method 'to_sql'
TIA!

0x6upsns

0x6upsns1#

版本

当涉及ActiveRecord对象时,有两种select类型,来自文档

  1. select与块。
    首先:取一个块,这样就可以像Array#select一样使用它。
    这将为作用域从数据库中构建一个对象数组,将它们转换为数组,并使用Array#select遍历它们。
    这就是你现在正在使用的。这个实现将加载每个post示例化一个Post对象,然后使用Array#select迭代每个Post,将结果过滤到一个Array中。这是非常低效的,不能与其他AR语义链接(例如whereorder等),并将导致很长的规模滞后。(这也是导致错误的原因,因为Array没有to_sql方法)
  2. select与列列表(如果愿意,也可以是String)
    第二:修改查询的SELECT语句,以便只检索某些字段...
    在您的情况下不需要此版本,因为您不希望将查询返回的列限制为帖子。

建议的解决方法:

相反,您需要的是一个WHERE子句,用于在将记录返回到ORM之前在数据库级别筛选记录。
您当前的筛选器为(X〈Y + 2)

Date.today < p.created_at.weeks_since(2)

这意味着“今天的日期”小于“创建时间”加上2周。
我们可以反转此条件,将其切换为“今天的日期减去2周”小于“创建时间”(X - 2〈Y),从而使查询更容易。

Date.today.weeks_ago(2) < p.created_at

这相当于p.created_at > Date.today.weeks_ago(2),我们可以使用标准ActiveRecord查询方法将其转换为where子句:

Post.where(created_at: Date.today.weeks_ago(2)...)

这将产生如下SQL:

SELECT 
  posts.*
FROM 
  posts.* 
WHERE 
  posts.created_at > '2022-10-28'

备注:

  • created_at是时间戳,因此使用Time.nowDate.today可能更好。
  • 从时区的Angular 来看,可能会涉及其他问题,因为您将执行特定于日期/时间的比较。
ni65a41a

ni65a41a2#

你需要在一个关系上调用to_sqlselect执行查询并给你结果,在结果上你没有to_sql方法。
有类似的questions,你可以看看,因为他们提供了一些替代品。

相关问题