Reputation: 6448
I'm a super newbie in RoR. Right now I'm working on this interesting Rails for Zombies exercises. And I got stuck with some syntax questions...
My code to this is:
Weapon.where(:zombie => "Ash")
But it won't work. If instead I typed:
Weapon.find(1)
I passed (since the first weapon belongs to the zombie Ash anyway).
My question is, what's wrong with my answer with this .where() method?
Thanks in advance.
Upvotes: 5
Views: 2979
Reputation: 1
the answers is Zombie.find(1).weapons
.. then you will success to find all Ash's weapons.
Upvotes: 0
Reputation: 195
I came across the same problem today but the accepted answer didn't work for me. I don't know whether the API has changed since 2010 but I got it to work by doing this:
Weapon.joins(:zombie).where(:zombies => {:name => "Ash"})
You can also get the same result by joining in the other direction although I think the first solution is what the question was looking for:
Zombie.where(:name => 'Ash').first.weapons
Upvotes: 2
Reputation: 11
Weapon.where(:zombie_id => Zombie.where(:name => "Ash"))
You can select from DB Weapon, the zombie_id
which name is Ash from DB Zombie.
Upvotes: 1
Reputation: 11154
If, like me, you were trying to attempt this via the Zombie Model, you will need to use first method. This is because where() returns a collection of Zombies.
i.e.
Zombie.where(:name => "Ash").first.weapons
This tutorial still teaches the old hash syntax, but ever since Ruby 1.9 you can (and should) use the new simplified format. This syntax even works in the Zombies tutorial:
Zombie.where(name:"Ash").first.weapons
Upvotes: 4
Reputation: 1656
Zombie.where(:name => "Ash").first.weapons
IMHO: I think that this way is more explicit: first, we are looking for a zombie, and then - want to take the first one's weapon.
Surely, you can look for the Weapon by zombie's id (Weapon.where(:zombie_id => SOME_ZOMBIE_ID)), BUT as for me - this is not the thing I want to see in my code half a year after - it is about more coding and wasting more time for understanding.
ps: Seems that my answer is a shorter version of Gerry's answer (see above) - sorry for that :)
Upvotes: 1
Reputation: 558
I think you passed using Weapon.find(1)
because there was only one weapon in the weapons table, but if you create another weapon, with the :id => 1 then your original syntax wouldn't work - cause it only returned the first weapon and not all the weapons.
I passed using, Zombie.find(1).weapons
which will return multiple entries for weapons associated with :id = 1, but was also thinking the same as you and wanted to search by :name and not :id.
I was also thinking about using the "where" attribute, but can't get it to work - and when I used @edgerunner answer it returned:
#<ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: zombie.name: SELECT "weapons".* FROM "weapons" WHERE "zombie"."name" = 'Ash'>
so I'm not sure if this is a limitation through the program or what - as it is, im still bit confused.
Upvotes: 0
Reputation: 195
This is how they intend you to do it (based on the video)
ash = Zombie.find(1) ash.weapons
Which should return an array of all the weapons ash owns. I tried for so long to use the count method and then I realized they just wanted the actual weapon items (array/list/whatever it is I'm just starting rails from a c++ and python background)
Upvotes: 2
Reputation: 11
In this context u can try this code:
z = Zombie.find("ID")
Weapon.where(:zombie_id => z)
Upvotes: 1
Reputation: 11
Since the zombie table is linked to the weapon table, you can use the following code: Zombie.find(1).weapons.all
FYI - Zombie ID 1 = Ash
Upvotes: 1
Reputation: 421
If you want a where clause you Now returns a single value then you could write
Zombie.where(:name => "ash").first
Upvotes: 3
Reputation: 14973
You should have nested the query as follows:
Weapon.where(:zombie => {:name => "Ash"})
That would give you the weapons that belong to the zombies whose names are 'Ash'
Upvotes: 7
Reputation: 2512
You generally use Model.find( )
if a single object is needed and it returns nil if not found. Whereas Model.where({:field => value})
returns an array of objects those matches the condition.
Upvotes: 2
Reputation: 5541
Not sure, also new to Rails3 queries, but doesnt :zombie expect to match a zombie object, not its name.
I would do Zombie.where(:name => "Ash").weapons
Upvotes: 2