Ruby on Rails 语法问题

5
我是一名RoR的超级新手。现在我正在做这个有趣的Rails for Zombies练习。但是我卡在了一些语法问题上...
我的代码如下:
Weapon.where(:zombie => "Ash")

但这样是行不通的。如果我输入以下内容:
Weapon.find(1)

我通过了(因为第一个武器本来就属于僵尸阿什)。我的问题是,我使用where()方法的答案有什么问题?谢谢提前。
图片描述:三张图片,分别为代码截图和两张结果截图。

1
这是教程的链接,对于那些感兴趣的人:http://railsforzombies.org/ - Chris Kimpton
谢谢您的提问。我也卡在了同样的部分,这里的回答(特别是ravi和DGM的回答)为我解释了原因。 - Gerry
14个回答

8
您应该将查询嵌套如下:
Weapon.where(:zombie => {:name => "Ash"})

那会给你属于名字为“Ash”的僵尸的武器。

这对我来说看起来很有希望... :) - Chris Kimpton

4
如果像我一样,你尝试使用Zombie模型来尝试这个,那么你需要使用第一个方法。这是因为where()返回了一个Zombies集合。
即:
Zombie.where(:name => "Ash").first.weapons

本教程仍然会教授旧的哈希语法,但自从Ruby 1.9以后,您可以(并且应该)使用新的简化格式。这种语法甚至在“Zombies”教程中也适用:

Zombie.where(name:"Ash").first.weapons

3
如果您想要一个where子句,使其仅返回单个值,则可以编写以下内容。
Zombie.where(:name => "ash").first

我不这么认为,因为问题要求“全部”。 - Chris Kimpton
@Chris 实际上这是有效的,你只需要在末尾添加.weapons来连接Weapons模型即可。 - Gerry

2

今天我遇到了同样的问题,但是接受的答案对我没有用。我不知道自2010年以来API是否发生了变化,但是我通过以下方式使其正常工作:

Weapon.joi­ns(:zombie­).where(:z­ombies => {:nam­e => "Ash"­})

您也可以通过相反的方向来加入,虽然我认为第一种解决方案是问题所寻求的。
Zombie.whe­re(:name => 'Ash'­).first.we­apons

2

这是他们希望您按照视频中的方式操作:

ash = Zombie.find(1) ash.weapons

这应该返回所有ash拥有的武器数组。我尝试使用计数方法很长时间,然后我意识到他们只想要实际的武器项目(数组/列表/无论它是什么,我只是从c++和python背景开始学习rails)。


2

我不确定,因为我也是Rails3查询的新手,但是:zombie不是期望匹配一个僵尸对象而不是它的名称吗。

我会这样做Zombie.where(:name => "Ash").weapons


谢谢Chris。但是看起来在Zombie类中没有设置weapons关系(而应该设置)。所以我得到了一个“#<NoMethodError: undefined method `weapons' for ...”错误。 - Di Wu
1
如果这是一对一的关系,尝试使用 Zombie.where(:name => "Ash").weapon - Damien Wilson

2

如果需要单个对象,则通常使用Model.find(),如果未找到则返回nil。而Model.where({:field => value})返回与条件匹配的对象数组。


1
仅仅是挑剔一点:从技术上讲,在Rails 3中,它并不返回一个数组。它返回一个ActiveRecord :: Relation(概念上是一个项目集合,但尚未进行任何查询)。Rails 3允许您将这些关系链接在一起,只有当您调用find_all或each或类似函数时才会得到答案。即使在那时,结果也不是一个数组,而是一个枚举器。 - DGM

1
Zombie.where(:name => "Ash").first.weapons

个人认为:我认为这种方式更明确:首先,我们正在寻找一个僵尸,然后 - 想要拿第一个僵尸的武器。

当然,您可以通过僵尸的ID查找武器(Weapon.where(:zombie_id => SOME_ZOMBIE_ID)),但对我来说 - 这不是我想在半年后看到的代码 - 它涉及更多编码和浪费更多时间来理解。

附言:似乎我的答案是Gerry答案的简短版本(请参见上文)- 对此我感到抱歉 :)


1
在这种情况下,您可以尝试使用此代码:
z = Zombie.find("ID")
Weapon.where(:zombie_id => z)

对于下一个练习,如果您想计算属于"Ash"的所有武器,只需键入:z.weapons.count - Henrique Silvestre

1

由于僵尸表与武器表相关联,您可以使用以下代码: Zombie.find(1).weapons.all

顺便提一下 - 僵尸 ID 1 = Ash


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接