Получить все вакансии, которые имеют дату старше сегодняшней даты и отфильтровать по пользователю и количеству отзывов на вакансию - PullRequest
0 голосов
/ 26 марта 2019

Мне нужно получить все задания, принадлежащие текущему пользователю, у которых дата старше, чем сегодняшняя, и мне также нужно отфильтровать задания с нулевыми отзывами.

Я пробовал следующее:

Job.joins(:user, :review).where("jobs.date < ? AND jobs.status = ? AND users.id = ?", Time.now, 3 , user.id).group("jobs.id").having("COUNT(reviews) = ?", 0)

В случае определенного идентификатора пользователя (3356) я должен получить одно задание, но не получаю.

Вот мои модели

class Job < ActiveRecord::Base
  belongs_to :user
  has_one :review
end

class User < ActiveRecord::Base
  has_many :jobs
  has_one :reviews
end

class Review < ActiveRecord::Base
  belongs_to :job
  belongs_to :user
end

status это Enum (который должен быть 3, который «принят»)

Что я делаю не так?Я не уверен, как правильно структурировать SQL, так что это, вероятно, проблема.Ценю вашу помощь.

Ответы [ 3 ]

2 голосов
/ 26 марта 2019

Вам нужно делать левые внешние объединения вместо внутренних, если вы выполняете внутреннее соединение, оно не будет работать, если у него 0 отзывов. У работы должен быть хотя бы один отзыв, тогда только она будет принимать запись о работе, кроме как в левой внешней присоединиться, запись всех заданий будет проходить независимо от того, есть ли у нее отзыв.

Job.left_outer_joins(:user, :reviews).where("jobs.date < ? AND jobs.status = ? AND users.id = ?", Time.now, 3 , user.id).group("jobs.id").having("COUNT(reviews) = ?", 0)
1 голос
/ 27 марта 2019

Мне нравится думать о таких проблемах, как разбивать их на более мелкие проблемы.

От вашего вопроса мы хотим ...

Получить все вакансии, которые:

  • имеет статус «принят»
Job.accepted
  • принадлежит текущему пользователю
Job.where(user: current_user)
  • дата старше, чем сегодняшняя дата
Job.where('date < ?', Time.zone.today)
  • с нулевыми отзывами
reviews = Review.all
Job.where.not(id: reviews.select(:job_id))

Этот немного отличается от других и использует подзапрос .


Теперь давайте соединим все это и определим метод в нашем классе Job:

class Job < ApplicationRecord
  enum status: [:other_status, :accepted]
  belongs_to :user
  has_one :review

  def self.unreviewed(user)
    accepted
      .where(user: user)
      .where('date < ?', Time.zone.today)
      .where.not(id: Review.select(:job_id))
  end
end

Это генерирует следующий SQL:

irb(main):002:0> puts Job.unreviewed(user).to_sql
SELECT "jobs".* FROM "jobs" WHERE "jobs"."status" = 0 AND "jobs"."user_id" = 1 AND (date < '2019-03-26') AND "jobs"."id" NOT IN (SELECT "reviews"."job_id" FROM "reviews")

Вы также можете найти некоторые спецификации, тестирующие это здесь .

1 голос
/ 26 марта 2019

joins (: review) будет выполнять внутреннее объединение Job и Review, что приведет к тому, что задания с 0 отзывами будут пропущены из результата.Попробуйте это:

Job.joins(:user).joins("left join reviews on reviews.job_id = jobs.id ").where("jobs.date < ? AND jobs.status = ? AND users.id = ?", Time.now, 3 , user.id).group("jobs.id").having("COUNT(reviews) = ?", 0)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...