How do I find all of the parasites belonging to the particular pet of a particular user?
Okay, I feel like I'm starting to come to SO for every activerecord query I have to write now and I'm starting to drag out my user/pet/parasite metaphor but here we go again.
In the following setup;
class User < ActiveRecord::Base
has_many :pets
has_many :parasites, :through => :pets
end
class Pet < ActiveRecord::Base
has_many :parasi开发者_Python百科tes
belongs_to :user
end
class Parasite < ActiveRecord::Base
belongs_to :pet
end
I want to write a search that will return all of the parasites that belong to Bob's cat (i.e. User.name = 'Bob' and Pet.animal = 'Cat').
I realise I can do this with the fairly drawn out and ugly
User.where(:name => 'Bob').first.pets.where(:animal => 'Cat').first.parasites
but I thought there should be a more succinct way of doing this.
All of my attempts to write a join statement to make this happen result in an ActiveRecord::Configuration error so I suspect I am going about this backwards. Once again, this seems like it should be easier than it is.
Thanks.
You try to achieve a has_many through has_many
association. This won't work using Rail's eager loading associations.
What you have to do is:
- join the
users
- join the
pets
- scope
users
down byusername
- scope
pets
down byuser_id
and theanimal
field
In ActiveRecord:
Parasite.joins(:pet).joins('INNER JOIN users').where('users.name = ? AND pets.user_id = users.id AND pets.animal = ?', @username, @animal)
Alternatively you can create a named scope:
class Parasite < ActiveRecord::Base
belongs_to :pet
scope :parasites_of, lambda {|owner, animal_type| joins(:pet).joins('INNER JOIN users').where('users.name = ? AND pets.user_id = users.id AND pets.animal = ?', owner, animal_type) }
end
Now you can call Parasite.parasites_of('Bob', 'Cat')
The resulting SQL Query will look like:
SELECT * FROM parasites
INNER JOIN users,
INNER JOIN pets ON pets.id = parasites.pet_id
WHERE
users.name = 'Bob'
AND
pets.user_id = users.id
AND
pets.animal = 'Cat'
(Hint: The .to_sql
method will show you the plain SQL query)
精彩评论