ActiveRecord查询:访问子查询中的外部字段

时间:2017-12-06 16:35:42

标签: ruby-on-rails ruby postgresql activerecord

我对如何进行有效的记录加入感到困惑。我有三个模型,用户,任务和响应。用户提交对任务的响应。我在ActiveRecord中使用has_many,through:pattern。

class Task < ApplicationRecord
  has_many :users, through: :responses
  has_many :responses
  validates :response_limit, presence: true

class User < ApplicationRecord
  has_many :responses
  has_many :tasks, through: :responses

class Response < ApplicationRecord
  belongs_to :task, optional: false
  belongs_to :user, optional: false

用简单的英语,我想创建一个给出查询的查询,返回所有的任务:

  1. 响应计数小于任务
  2. 中的:response_limit字段
  3. 用户尚未回复。
  4. 我能够通过这个嵌套查询来满足#2,这是我从之前的问题中得到的。

    Task.where.not(id: Response.select(:task_id).where(user_id: params[:user_id]))
    

    然而,我很难满足第一个。我抓住它并得到了这个:

    Task.where.not(id: Response.select(:task_id).where(user_id: params[:user_id])).where('response_limit > (?)', Response.where(task_id:task.id).count)
    

    我的问题是我不确定如何将task_id从外部查询中获取到Response子查询中。

2 个答案:

答案 0 :(得分:1)

为此,您可以尝试使用SQL GROUP BY和HAVING子句来帮助您计算响应并根据条件过滤它们

Task.select("tasks.*, COUNT(responses.id) AS response_count")
    .joins(:responses)
    .group("tasks.id")
    .where.not(id: Response.select(:task_id).where(user_id: params[:user_id]))
    .having("COUNT(responses.id) < tasks.response_limit")

答案 1 :(得分:1)

您可以通过

获得任务的响应次数
    Task.response.count

然后简单地将它与任务的response_limit

进行比较