Rails 5范围问题

Posted

技术标签:

【中文标题】Rails 5范围问题【英文标题】:Rails 5 scope issue 【发布时间】:2019-01-25 14:44:56 【问题描述】:

在带有 Postgresql 的 rails 5 中,我正在编写一个范围来按日期选择状态项。我的模型是:

class Status < ApplicationRecord
  scope :in_month, ->(date)where("status_date = ?", date) if date.present?
end

但是,在rails console 中,尝试使用范围时出现以下错误。 ```

2.4.0 :010 > Status.in_month("2018-06-01")
  Status Load (11.7ms)  SELECT  "statuses".* FROM "statuses" WHERE (status.status_date = '2018-06-01') LIMIT $1  [["LIMIT", 11]]
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR:  missing FROM-clause entry for table "status"
LINE 1: SELECT  "statuses".* FROM "statuses" WHERE (status.status_da...
                                                    ^
: SELECT  "statuses".* FROM "statuses" WHERE (status.status_date = '2018-06-01') LIMIT $1

请注意,由于某种原因,它试图访问表“状态”,而不是“状态”。

我到底做错了什么?这几乎直接来自 RailsGuide。

编辑和“修复”

哼...Rails 控制台显然处于错误状态。我在下面的 cmets 之后重新启动了控制台,发现我的查询运行良好。请注意,这种 WHERE 子句格式需要引号,并且statusesstatus 的正确复数形式。

重启后,praga2050 描述的where(status_date: date) 格式有效,Kedarnag Mukanahallipatna 建议的where("statuses.status_date = ?", date) 也有效。

经验教训:reload! 不会重新加载模型中的更改;您必须重新启动控制台才能识别模型更改。看到这个答案:https://***.com/a/5428421/446464

【问题讨论】:

这是整个Status 类吗? ApplicationRecord 有什么事吗?该范围根本不应该添加任何表前缀。 你可以试试scope :in_month, -&gt;(date)where("statuses.status_date = ?", date) if date.present? 确保将 statuses 括在 ``@KedarnagMukanahallipatna - 您的示例中有一个额外的空间,但是通过该修复它也可以正常工作 - 请参阅我的编辑。 【参考方案1】:

我不确定你为什么将字符串放在 Where 子句中

scope :in_month, ->(date)where("status_date = ?", date) if date.present?

应该像下面这样改变。

下面的一个应该适合你。

scope :in_month, ->(date)where(status_date: date) if date.present?

【讨论】:

字符串格式在 Ruby on Rails 指南 (guides.rubyonrails.org/active_record_querying.html#scopes) 第 14.2 节中明确描述。您的方法是另一种方法,但失败并出现相同的错误。【参考方案2】:

我认为您错过了 Rails 中命名约定的要点。

模型类名是单数的,会自动映射到复数的数据库表名。

据此,您可以将您的模型名称更改为statuses

或者设置一个在rails模型中使用的表名:

class Status < ApplicationRecord
  self.table_name = 'status'

  scope :in_month, ->(date)  where(status_date: date) if date.present? 
end

【讨论】:

嗯.. "statuses" 是 "status" 的复数形式,你可以看到 Rails 正确识别出他们的 SQL 语句的第一部分是SELECT "statuses".* FROM "statuses" WHERE...。 WHERE 子句中的复数形式失败。

以上是关于Rails 5范围问题的主要内容,如果未能解决你的问题,请参考以下文章

Rails 中无限时间范围的问题

Rails 包含范围

rails 3.0中的多个范围

具有多态模型的 Rails 范围

rails 范围检查关联是不是不存在

带有关联的 Rails 范围