Область Rails для возврата записей, в которых ВСЕ ассоциации соответствуют критериям

У меня проблема с написанием области для возврата записей, в которых ВСЕ ассоциации has_many соответствуют критериям.

У меня есть эти модели:

class Product
  has_many :listings
end

class Listing
  belongs_to :product
  belongs_to :issue
end

class Issue
  has_many :listings
end

По сути, продукт может быть указан в нескольких разных выпусках. Я хочу иметь возможность получить все продукты, у которых нет списков в конкретном выпуске. Пока у меня есть эта область в моей модели продукта:

scope :not_listed_in, lambda { |issue|
  joins(:listings)
    .where("listings.issue_id != ?", issue.id)
}

Это не работает, так как он найдет все продукты, хотя бы одно перечисление которых не входит в выдачу. Мне нужен какой-то способ запросить все продукты, которые НЕ имеют списков в конкретном выпуске.


person jhummel    schedule 28.01.2013    source источник


Ответы (1)


Предполагая, что вы используете ActiveRecord, вы можете добиться этого, найдя все продукты и удалив продукты в проблеме. Обычно это приводит к массиву, поэтому в приведенном ниже коде я сделал один дополнительный запрос к базе данных, чтобы он возвращал результат с заданной областью, чтобы вы могли каскадировать другие предложения «где» к результату.

class Product < ActiveRecord::Base
  has_many :listings
  scope :not_listed_in, lambda { |issue|
    id_list = Product.pluck(:id) - issue.products.pluck(:id)
    Product.where(id:id_list)
  }
end

class Listing < ActiveRecord::Base
  belongs_to :product
  belongs_to :issue
end

class Issue < ActiveRecord::Base
  has_many :listings
  has_many :products, through: :listings
end
person Troy    schedule 29.01.2013
comment
В итоге я сделал что-то подобное, используя #reject, но мне так больше нравится. Спасибо! - person jhummel; 30.01.2013
comment
Я обновил свой ответ - я заметил классный метод AR - pluck - который создает простой запрос к БД, захватывая только один столбец и возвращая массив значений - именно то, что здесь было нужно. - person Troy; 30.01.2013