Rails ActiveRecord 中 many-to-many select 问题

ftiasch · 2014年11月29日 · 最后由 nanometer 回复于 2014年11月29日 · 1939 次阅读

Model 是这样的

class Contest < ActiveRecord::Base
  has_many :contest_problems
  has_many :problems, through: :contest_problems
end

class Problem < ActiveRecord::Base
  has_many :contest_problems
  has_many :contests, through: :contest_problems
end

class ContestProblem < ActiveRecord::Base
  belongs_to :contest
  belongs_to :problem
end

Migration 是这样的

class CreateContestProblems < ActiveRecord::Migration
  def change
    create_table :contest_problems do |t|
      t.integer :contest_id
      t.integer :problem_id
      t.string  :index,     limit: 2

      t.timestamps
    end
  end
end

现在想干这么一个事情:

c = Contest.find(1)
p = c.problems.find(1).index

Rails 在做这个查询的时候,INNER JOIN 了 contest_problems,但是却不会把 contest_problems.* 给 SELECT 进来,所以没办法做这个查询。有什么好的解决方法吗?

可以直接 includes(:contests) 或定义一个 scope

class Problem < ActiveRecord::Base
  has_many :contest_problems
  has_many :contests, through: :contest_problems
  scope :include_contests, ->{ includes(:contests) }
end

c.problems.include_contests.find(1)

#1 楼 @xiaohui_zhangxh 问题其实是我借了 ID 问的 - -,就是我有多个 contests 和 problems,一个 problem 可能会出现在多个 contests 里面,然后每个 contest 会对他的 problems 打上 A, B, C, ... 这样的 index。

这个 index 是存在 contest_problems 里面的,所以 includes(:contests) 肯定是有问题的。即使不是说这个问题, includes(:contests_problems) 会生成一个:

SELECT `contest_problems`.* FROM `contest_problems`  WHERE `contest_problems`.`problem_id` IN (...)

但事实上我需要的是:

SELECT `contest_problems`.* FROM `contest_problems`  WHERE `contest_problems`.`contest_id` = 1 AND `contest_problems`.`problem_id` IN (...)
需要 登录 后方可回复, 如果你还没有账号请 注册新账号