如何在联接查询中使用范围?

时间:2019-04-23 08:50:11

标签: ruby-on-rails

我想使用联接表的作用域。 目的是为具有带有特定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)})

正确的语法是什么?

1 个答案:

答案 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 []>