Rails基于多个模型加入

时间:2015-04-01 19:02:48

标签: ruby-on-rails postgresql

我有四个模型:UserProductPurchaseWatchedProduct

我正在尝试获取符合以下条件之一的产品列表:

  1. 我创造了这个产品。
  2. 我买了这个产品。
  3. 该产品是免费的,我已经主演过"或者"观看"它。
  4. 这是我到目前为止所做的:

    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模型列表,而不是ID列表或ActiveRecord关系列表。我是新手,但有没有办法在一次连接中完成所有这些,而不是3次查询,减少和重新查找?

2 个答案:

答案 0 :(得分: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个查询返回一系列独特的产品。

答案 1 :(得分: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