2015-04-01 3 views
1

У меня есть четыре модели: User, Product, Purchase и WatchedProduct.Rails Регистрация на основе нескольких моделей

Я пытаюсь получить список продуктов, которые отвечают одному из следующих критериев:

  1. Я создал продукт.
  2. Я купил продукт.
  3. Продукт является бесплатным, и я «снял» или «просмотрел» его.

Это то, что я до сих пор:

class User < ActiveRecord::Base 
    ... 

    def special_products 
    product_ids = [] 

    # products I created 
    my_products = Product.where(:user_id => self.id).pluck(:id) 
    # products I purchased 
    my_purchases = Purchase.where(:buyer_id => self.id).pluck(:product_id) 
    # free products I watched 
    my_watched = WatchedProduct.where(:user_id =>self.id).joins(:product).where(products: { price: 0 }).pluck(:product_id) 

    product_ids.append(my_products) 
    product_ids.append(my_purchases) 
    product_ids.append(my_watched) 

    product_ids # yields something like this => [[1, 2], [], [2]] 

    # i guess at this point i'd reduce the ids, then look them up again... 

    product_ids.flatten! 
    product_ids & product_ids 
    products = [] 
    product_ids.each do |id| 
     products.append(Product.find(id)) 
    end 
    products 

    end 
end 

То, что я пытаюсь сделать, это получить список Product моделей, а не список идентификаторов или список ActiveRecord отношений. Я очень новичок в объединении, но есть ли способ сделать все это в одном соединении вместо трех запросов, уменьшения и повторного поиска?

ответ

1

Сначала я люблю добавлять несколько областей

class Product < ActiveRecord::Base 
    scope :free, -> { where(price: 0) } 
    scope :bought_or_created_by, lambda do |user_id| 
    where('user_id = :id OR buyer_id = :id', id: user_id) 
    end 
end 
class WatchedProduct < ActiveRecord::Base 
    scope :by_user, ->(user_id) { where(user_id: user_id) } 
end 

Тогда запросы

special_products = (Product.bought_or_created_by(id) + Product.joins(:watched_products).free.merge(WatchedProduct.by_user(id)).uniq 

Это возвращает массив уникальных продуктов с использованием 2 запросов.

+0

'buyer_id' принадлежит к Модель покупки. Должен ли я просто переместить третий вариант этой модели? – Jeff

+0

o да, это моя ошибка, я исправлю свой ответ –

+0

Это просто, чтобы упростить запрос, если он не работает, то единственной частью, которая нуждается в исправлении, является 'Product.joins (: watched_products)', какова связь между ' продукт' и 'watched_products'? –

0

Хотя я не уверен в вашей модели ассоциаций, но да, вы можете делать все эти вещи в одном запросе как-то вроде этого:

Product.joins([{:user => :watched_products}, :buyer, :purchases]).where(["users.id = :current_buyer && buyers.id = :current_buyer && watched_products.user_id = :current_buyer && purchases.buyer_id = :current_buyer, products.price = 0", :current_buyer => self.id]) 

Я предполагаю,

Product belongs_to user and buyer 
Product has_many purchases 
User has_many watched_products 
Смежные вопросы