質問

I have this model:

class Product < ActiveRecord::Base
  belongs_to :shop

  has_many :categories_products, dependent: :destroy, autosave: true
  has_many :categories, through: :categories_products

  has_many :favorite_products, dependent: :destroy
  has_many :users, through: :favorite_products

  scope :by_shop_category, ->(shop_id, category_id) { eager_load(:categories_products).where(shop_id: shop_id, categories_products: {category_id: category_id}) }
  scope :by_category, ->(category_id) { eager_load(:categories_products).where(categories_products: {category_id: category_id}) }

I have these 2 queries:

favorite_products = Product.where(id: current_user.product_ids).by_category(@category.id)
favorite_shop_products = Product.by_shop_category(current_user.shop_ids, @category.id)

The first returns all the products the current user has favorited from a certain category. The second returns all the products from a certain category from all shops the current user has favorited.

Obviously if a user has favorited a product belonging to a shop that they've favorited then the product will appear in both sets.

What's the cleanest performant way to come up with a set of unique results?

役に立ちましたか?

解決 2

I landed on this as the simplest most performant option because it uses SQL to make the exclusion:

favorite_products = Product.where(id: current_user.product_ids).by_category(@category.id)
favorite_shop_products = Product.where.not(id: current_user.product_ids).by_shop_category(current_user.shop_ids, @category.id)
@products = favorite_products + favorite_shop_products

他のヒント

favorite_products | favorite_shop_products

uses the Array union operator to combine the two sets and eliminate duplicates. This may or may not be performant depending on the size of the result sets.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top