Reputation: 1484
I have 4 models: Person
, School
, Home
, Office
.
They all have the attributes id
and name
My main model is person.rb:
class Person < ActiveRecord::Base
has_and_belongs_to_many :school, join_table: :school_persons
has_and_belongs_to_many :home, join_table: :home_persons
has_and_belongs_to_many :office, join_table: :office_persons
end
I want to find all persons that have at least 10 associated contents.
I tried joining it with one model, but I want the content that has at least 10 associated content from all the models.
person.find_by_sql("
SELECT person.*
FROM persons
INNER JOIN office_persons ON persons.id = office_persons.person_id
GROUP BY persons.id
HAVING COUNT(office_persons.art_id) = 10
").count
How should I approach this?
Upvotes: 0
Views: 78
Reputation: 18464
There're several ways:
You can employ a counter_cache
-like column for count (but you'll have to add callbacks to all the related models to update it on create/delete as original counter_cache does)
Just use separate counter caches for each relation (as of rails 4 counter caches should work on HABTM relations) and select by sum of these
Heavy sql subqueries (usually not recomended, unless it is a one-off task or you have little data and thus no performance problems)
Query like:
SELECT persons.* FROM persons
WHERE ((select count(*) from office_persons where person_id=persons.id) +
(select count(*) from home_persons where person_id=persons.id)+
(select count(*) from school_persons where person_id=persons.id)) >= 10
has_many through:...
with single join table and flag for home
/office
/etc thus have single counter cache and ability to just Upvotes: 1