5

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.

alt text

alt text

alt text

2
  • 1
    Here is the link to the tutorial, for those interested: railsforzombies.org Commented Dec 30, 2010 at 15:00
  • Thanks for asking the question. I got stuck at the same part and the responses here (especially those of ravi and DGM) explained the reason for me. Commented Aug 5, 2011 at 15:10

14 Answers 14

7

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'

Sign up to request clarification or add additional context in comments.

1 Comment

This looks hopeful to me... :)
4

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

Comments

3

If you want a where clause you Now returns a single value then you could write

Zombie.where(:name => "ash").first

2 Comments

I dont think so, since question asks for "all"
@Chris Actually this does work, you just need to add .weapons to the end of it to join the Weapons model.
2

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

2 Comments

thanks Chris. but it seems that the weapons relationship was not set up in the Zombie class (while it should be). so I got a "#<NoMethodError: undefined method `weapons' for ..." error
Try Zombie.where(:name => "Ash").weapon if it's a one to one relationship.
2

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.

1 Comment

Just a nitpick: Technically, in rails 3, it does not return an array. It returns an ActiveRecord::Relation (which conceptually is a collection of items, but no query has been made yet). Rails 3 lets you chain these relations together, and you only get an answer when you call find_all or each or similar. Even then the result is not an array, but an enumerator.
2

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)

Comments

2

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.joi­ns(:zombie­).where(:z­ombies => {:nam­e => "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.whe­re(:name => 'Ash'­).first.we­apons

Comments

1

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

Comments

1

Weapon.where(:zombie_id => '1') => [#]

Comments

1

In this context u can try this code:

z = Zombie.find("ID")
Weapon.where(:zombie_id => z)

1 Comment

and for the next exercise if u wanna count all the Weapons that belongs to "Ash" u simple type: z.weapons.count
1
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 :)

Comments

1
Weapon.whe­re(:zombie­_id => Zombi­e.where(:n­ame => "Ash"­))

You can select from DB Weapon, the zombie_id which name is Ash from DB Zombie.

Comments

0

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.

1 Comment

' Zombie.find_by_name('Ash').weapons' works and uses the name attribute, but i dont think find_by_name has been yet discussed
0

the answers is Zombie.find(1).weapons .. then you will success to find all Ash's weapons.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.