开发者

Rails has_many, find only those with children

开发者 https://www.devze.com 2023-02-19 20:07 出处:网络
My \"products\" table has_many :registered_products. I want to use something like products.find(:has_registered_products)

My "products" table has_many :registered_products.

I want to use something like

products.find(:has_registered_products) 

where that will return only the p开发者_开发技巧roducts that also have an entry in the registered_products table. How could I achieve this?


As long as you have a foreign_key for the product in the registered_products table you can do:

has_many :registered_products
named_scope :with_registered_products, :joins => :registered_products

# if you're using rails 3
scope :with_registered_products, joins(:registered_products)

and that will only return products that have at least one associated registered product.


This will handle the duplication.

Product.joins(:registered_products).uniq


As Jakob points out, if there are multiple child records, you need to ensure that you are not returning multiple parent objects.

Using the "select distinct" will work, but the select statement could interfere when this scope is combined with other scopes.

Another option is to ensure that you join to a child table that only has unique records. You can do this by composing your join as follows

class Product < ActiveRecord::Base
 has_many registered_products

 scope :with_registered_products, joins('join (select distinct product_id from registered_products) rp123456 on rp123456.product_id = products.id')
end


class Product
  has_many :registered_products
end

List of Products (with at-least one registered product) - Eager loaded registered products

Product.all(:include => :registered_products, 
  :conditions => "registered_products.id IS NULL")

List of Products (with at-least one registered product) - Without eager loading

Product.all(:joins => :registered_products)


You could use counter_cache (http://railscasts.com/episodes/23-counter-cache-column). It should be faster than actually doing the join just to find out if there are any children.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号