我有四个模型:User
,Product
,Purchase
和WatchedProduct
。
我正在尝试获取符合以下条件之一的产品列表:
这是我到目前为止所做的:
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次查询,减少和重新查找?
答案 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