RAILS: How to query for all the objects whose every association have an attribute that is not null

断了今生、忘了曾经 提交于 2019-12-10 22:40:03

问题


Im working on Rails 3.0.5 and PostgreSQL.

I have a model Offer, that has many Products.

class Offer < ActiveRecord::Base
  has_many  :products
end

class Product < ActiveRecord::Base
   belongs_to :offer
end

The product has an id that updates when you register it in a third party service. Lets call it service_id. I want an Offer scope, that gets all the offers that have every single product registered in the third party service. In other words, I'm only interested in the offer instance if all of its products have a service id.

The offer scope: joins(:products).where("products.service_id is not NULL"), just returns the offers that have at least one product that is not null.

Any help would be appreciated.

(PS: Sorry for the title, I tried to explain it the best I could.)

EDIT:

For example: If I have 2 offers: Offer1 and Offer2. Offer1 has products p1 and p2, and Offer2 has products p3 and p4. Let's say p1, p2 and p3 have a service but p4 doesn't. The query should return only Offer1.


回答1:


This is another approach.

Offer.find_by_sql("SELECT * FROM offers o WHERE NOT EXISTS (SELECT * FROM products WHERE products.offer_id = o.id AND service_id IS NULL)")

Even do the idea of an ORM is that you abstract the SQL, in this kind of complex query, I think it is better to pick the simplest solution and not complicate the query even more.




回答2:


i believe what you want to do is define a scope on products and then join that scope to your scope Offer:

class Product < ActiveRecord::Base

scope :serviced, where('products.service_id is not NULL')

end

class Offer < ActiveRecord::Base

scope :with_serviced_products, joins(:products) & Product.serviced

end

EDIT:

hmm, well now that i understand your question, I don't have a complete answer for you. just some thoughts. Sounds like you're going to need at least one sub-select querys and some Group Bys. What if..

You use rails to keep a counter-cache on your Offer model of products_count.

You count the number of serviced products for each Offer. Something like,

Product.serviced.group_by(:offer_id).count

And then select only the Offers where the two counts, it's products_count and the result of the sub-query, match?



来源:https://stackoverflow.com/questions/6430761/rails-how-to-query-for-all-the-objects-whose-every-association-have-an-attribut

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!