为关联表添加JOIN

时间:2013-03-06 20:22:52

标签: ruby-on-rails ruby-on-rails-3.2 rails-activerecord

我的组织类看起来像这样:

has_many Students

我的学生课程如下所示:

has_many Klasses
belongs_to Organization

我的 Klass 类看起来像这样:

some field named : price
scope :top_expensive_classes, joins(:students).order('price DESC')
belongs_to Student

我的查询如下:

@results = Klass.top_expensive_classes.where(organization_id: params[:id]).limit(RESULT_SET_COUNT)

请注意,它以Klass开头,所以这就是问题所在,因为我正在搜索organization_id的where类但是不在Klass中,它在Student类中,所以不知何故我应该在某个地方引入一个连接来解决这个问题但是无法理解。

1 个答案:

答案 0 :(得分:1)

我认为真正的问题是你的关联可能不正确。

  • 学生有很多课程
  • 班级有很多学生

但你拥有的是

  • 学生有很多课程
  • 班级属于单个学生

这并没有多大意义(至少在任何情况下,我见过一个班级和学生互动)。您应该创建多对多关系,而不是KlassStudent之间的一对多关系。

class Student < ActiveRecord::Base
  has_many :klasses, through: :student_klasses
  has_many :student_klasses
end

class Klass < ActiveRecord::Base
  has_many :students, through: :student_klasses
  has_many :student_klasses
end

class StudentKlass < ActiveRecord::Base
  belongs_to :student
  belongs_to :klass
end

如果您拥有这些正确的关联,则需要在.joins类的:students关联上调用Klass。你可以不用范围。

Klass.joins(:students).where("students.organization_id = ?", params[:id]).order('price DESC').limit(RESULT_SET_COUNT)

在ActiveRecord查询中阅读the guide


以下是(使用上面的确切模型定义)的证明,关联的顺序很重要。

irb(main):001:0> s = Student.create(name: "Deefour")
  SQL (3.6ms)  INSERT INTO "students" ("created_at", "name", "updated_at") VALUES (?, ?, ?)  [["created_at", Fri, 08 Mar 2013 01:33:32 UTC +00:00], ["name", "Deefour"], ["updated_at", Fri, 08 Mar 2013 01:33:32 UTC +00:00]]
=> #<Student id: 1, name: "Deefour", created_at: "2013-03-08 01:33:32", updated_at: "2013-03-08 01:33:32">
irb(main):002:0> kk = []
=> []

irb(main):003:0> kk << Klass.create(title: "Klass 1")
  SQL (0.3ms)  INSERT INTO "klasses" ("created_at", "title", "updated_at") VALUES (?, ?, ?)  [["created_at", Fri, 08 Mar 2013 01:34:06 UTC +00:00], ["title", "Klass 1"], ["updated_at", Fri, 08 Mar 2013 01:34:06 UTC +00:00]]
=> [#<Klass id: 1, title: "Klass 1", created_at: "2013-03-08 01:34:06", updated_at: "2013-03-08 01:34:06">]

irb(main):004:0> kk << Klass.create(title: "Klass 2")
  SQL (0.3ms)  INSERT INTO "klasses" ("created_at", "title", "updated_at") VALUES (?, ?, ?)  [["created_at", Fri, 08 Mar 2013 01:34:14 UTC +00:00], ["title", "Klass 2"], ["updated_at", Fri, 08 Mar 2013 01:34:14 UTC +00:00]]
=> [#<Klass id: 1, title: "Klass 1", created_at: "2013-03-08 01:34:06", updated_at: "2013-03-08 01:34:06">, #<Klass id: 2, title: "Klass 2", created_at: "2013-03-08 01:34:14", updated_at: "2013-03-08 01:34:14">]

irb(main):005:0> s.klasses = kk
  Klass Load (0.1ms)  SELECT "klasses".* FROM "klasses" INNER JOIN "student_klasses" ON "klasses"."id" = "student_klasses"."klass_id" WHERE "student_klasses"."student_id" = ?  [["student_id", 1]]
  SQL (0.4ms)  INSERT INTO "student_klasses" ("created_at", "klass_id", "student_id", "updated_at") VALUES (?, ?, ?, ?)  [["created_at", Fri, 08 Mar 2013 01:34:29 UTC +00:00], ["klass_id", 1], ["student_id", 1], ["updated_at", Fri, 08 Mar 2013 01:34:29 UTC +00:00]]
  SQL (0.1ms)  INSERT INTO "student_klasses" ("created_at", "klass_id", "student_id", "updated_at") VALUES (?, ?, ?, ?)  [["created_at", Fri, 08 Mar 2013 01:34:29 UTC +00:00], ["klass_id", 2], ["student_id", 1], ["updated_at", Fri, 08 Mar 2013 01:34:29 UTC +00:00]]
=> [#<Klass id: 1, title: "Klass 1", created_at: "2013-03-08 01:34:06", updated_at: "2013-03-08 01:34:06">, #<Klass id: 2, title: "Klass 2", created_at: "2013-03-08 01:34:14", updated_at: "2013-03-08 01:34:14">]

irb(main):006:0> Student.first.klasses.map(&:id)
  Student Load (0.2ms)  SELECT "students".* FROM "students" ORDER BY "students"."id" ASC LIMIT 1
  Klass Load (0.1ms)  SELECT "klasses".* FROM "klasses" INNER JOIN "student_klasses" ON "klasses"."id" = "student_klasses"."klass_id" WHERE "student_klasses"."student_id" = ?  [["student_id", 1]]
=> [1, 2]