【发布时间】:2018-06-27 18:23:45
【问题描述】:
我很难在 Rails 中找出一些东西。这可能与我对 SQL 的知识非常有限有关,因为我对 Rails 非常了解。我正在使用 Rails 5。
我有两个模型:申请人和申请。
class Applicant < ApplicationRecord
has_one :application
has_many :skills
accepts_nested_attributes_for :application
accepts_nested_attributes_for :skills,
reject_if: ->(skill) { skill[:name].empty? || skill[:experience].empty? }
validates_with ApplicantValidator
end
class Application < ApplicationRecord
belongs_to :applicant
has_many :notes
VALID_STATUSES = ["in review", "accepted", "declined", "closed"]
validates_length_of :why_interested, minimum: 25
validates :accept_terms, acceptance: true
validates :status, inclusion: { in: VALID_STATUSES }
before_validation :set_status
private
def set_status
self.status ||= "in review"
end
end
我想向申请人模型添加一个范围:active,该模型仅返回申请状态为“审查中”的申请人。但是,我找不到在作用域 proc 内访问应用程序的方法。
对于与孩子有has_many 关系的情况,我看到了其他建议,但在我的情况下它们不起作用。
我怀疑它会有所作为,但我使用的是 Postgres。我最接近的解决方案是添加它,但是当我运行 RSpec 时,它说应用程序表需要一个 FROM 子句。我不知道如何实现。
scope :active, -> { joins(:application).where('"application"."status" = "in review"') }
【问题讨论】:
-
SQL中的双引号用于引用标识符(例如表名和列名),单引号用于字符串文字,表名也是复数。你可能想说
where('"applications"."status" = 'in review'')或者更好的where(applications: { status: 'in review' }),这样ActiveRecord 就可以引用了。 -
我将其更改为
scope :active, -> { joins(:application).where({ applications: { status: "in review" } }) },它不再引发错误,但范围不应该返回空。 -
应该发现它不是什么?您也可以使用
where(id: Application.select(:applicant_id).where(status: 'in review')),但这应该会为has_one关联产生相同的结果。 -
有趣 - 看起来第二种方式在 Rails 控制台中有效,但在 RSpec 中无效。我认为问题一定出在我的工厂。谢谢!
-
两个版本都应该使用
has_one做同样的事情。第二个往往更适合has_many关联,因为它避免了 JOIN 可能引入的重复。
标签: sql ruby-on-rails activerecord