I have two models: a ownerand a pet. Owner has_many :petsand pet belongs_to :owner.
owner
pet
has_many :pets
belongs_to :owner
What I want to do is to capture only those owners who have pets that are ALL weighing more than 30 pounds.
#app/models/owner.rb class Owner < ActiveRecord::Base has_many :pets #return only those owners that have heavy pets end #app/models/pet.rb class Pet < ActiveRecord::Base belongs_to :owner scope :heavy, ->{ where(["weight > ?", 30])} end
Here is what is in my database. I have three owners:
The request should return only Neil. Right now, my attempts are returning Neil and Bob.
, , owner_ids, 1 , owner_ids, 1 , , id , ?
owner_ids
- :
scope :not_heavy, -> { where('weight <= ?', 30) }
...
owner_ids = Pet.heavy.pluck(:owner_id) - Pet.not_heavy.pluck(:owner_id) owners_with_all_pets_heavy = Owner.where(id: owner_ids)
owner_id , , group by having:
owner_id
group by
having
scope :heavy, -> { group("owner_id").having(["count(case when weight <= ? then weight end) = 0", 30]) }
, Rails-ActiverRecord:
scope :heavy, -> { where.not(owner_id: Pet.where(["weight <= ?", 30]).distinct.pluck(:owner_id)).distinct }
owner_id, ( ) .
, , - :
scope :heavy, -> { group("owner_id").joins(:pets).having("min(pets.weight) >= ?", 30)}
,
scope :light, -> { group("owner_id").joins(:pets).having("max(pets.weight) < ?", 30)}
, , Pet
, :
Owner.where(Pet.where.not("pets.owner_id = owners.id and pets.weight < ?", 30).exists)
, 30, , , .
.
(owner_id, weight).
uniq :
uniq
scope :heavy_pets, -> { uniq.joins(:pets).merge(Pet.heavy) }
, distinct.
distinct