我想使用联接表的作用域。 目的是为具有带有特定stat_id(例如15)的报告的汽车编写范围。
Rails 5.2.3
class Author < ApplicationRecord
belongs_to :report
class Report < ApplicationRecord
has_many :authors
scope :with_stat, ->(s) {
where(stat_id: s)
}
这很好:
Autor.joins(:report).where(reports: {stat_id: 15})
如果范围更复杂。如何使用Report类的范围? 这不起作用:
Autor.joins(:report).where(reports: {with_stat(15)})
正确的语法是什么?
答案 0 :(得分:1)
该范围不会为您提供正确的查询。
您想要的是Author.joins(:report).where(reports: { stat_id: 1 })
。给出一个查询:
Author Load (1.0ms) SELECT "authors".* FROM "authors" INNER JOIN "reports" ON "reports"."id" = "authors"."report_id" WHERE "reports"."stat_id" = $1 LIMIT $2
如果您使用范围,则会发生以下情况:
irb(main):004:0> Author.joins(:report).where(Report.with_stat(1))
Report Load (1.6ms) SELECT "reports".* FROM "reports" WHERE "reports"."stat_id" = $1 [["stat_id", 1]]
Author Load (0.6ms) SELECT "authors".* FROM "authors" INNER JOIN "reports" ON "reports"."id" = "authors"."report_id" LIMIT $1 [["LIMIT", 11]]
=> #<ActiveRecord::Relation []>
irb(main):005:0> Author.joins(:report).where(report: Report.with_stat(1))
Author Load (2.1ms) SELECT "authors".* FROM "authors" INNER JOIN "reports" ON "reports"."id" = "authors"."report_id" WHERE "authors"."report_id" IN (SELECT "reports"."id" FROM "reports" WHERE "reports"."stat_id" = $1) LIMIT $2 [["stat_id", 1], ["LIMIT", 11]]
=> #<ActiveRecord::Relation []>
稍后使用子查询,该子查询应给出相同的结果,但效率较低。
您可以做的是将范围放在关联的另一端:
class Author < ApplicationRecord
belongs_to :report
scope :with_stat, ->(s){
joins(:report).where(reports: {stat_id: s})
}
end
irb(main):010:0> Author.joins(:report).where(reports: { stat_id: 1 })
Author Load (1.1ms) SELECT "authors".* FROM "authors" INNER JOIN "reports" ON "reports"."id" = "authors"."report_id" WHERE "reports"."stat_id" = $1 LIMIT $2 [["stat_id", 1], ["LIMIT", 11]]
=> #<ActiveRecord::Relation []>