NoMethodError:未定义的方法`RuntimeError'

时间:2011-04-22 15:45:12

标签: ruby-on-rails ruby error-handling

我在Ruby库中编写了一些代码(偶然在Rails中使用),引发了一个类似于下面的RuntimeError:

class MyClass
  def initialize(opts = {})
     # do stuff
     thing = opts[:thing]
     raise RuntimeError "must have a thing!" unless thing.present? && thing.is_a?(Thing)
     # more stuff
  end
end

当我运行新的新的rspec规范时,看起来有点像:

it "should raise an error if we don't pass a thing" do
  lambda {
    my_class = MyClass.new(:thing => nil)
  }.should raise_exception(RuntimeError)
end

我不断得到一些奇怪的东西:

expected RuntimeError, got 
#<NoMethodError: undefined method `RuntimeError' for #<MyClass:0xb5acbf9c>>

3 个答案:

答案 0 :(得分:11)

你可能已经发现了这个问题......啊,单个字符的错误,doncha爱他们?

在这里。

WRONG:

 raise RuntimeError "must have a thing!" unless thing.present? && thing.is_a?(Thing)

RIGHT:

 raise RuntimeError, "must have a thing!" unless thing.present? && thing.is_a?(Thing)

当然,您也可以继续完全省略RuntimeError:

 raise "must have a thing!" unless thing.present? && thing.is_a?(Thing)

因为它是默认的......

答案 1 :(得分:5)

您缺少逗号:

raise RuntimeError, "must have a thing!" unless thing.present? && thing.is_a?(Thing)
                  ^

答案 2 :(得分:1)

只是添加一些解释:在Ruby中,变量引用和消息发送之间存在歧义。

foo
Foo

是否意味着“取消引用名为foo(或Foo)的变量”“发送消息:foo(或者:Foo),默认接收器为空参数列表“。

这种含糊不清的解决方法如下:

  1. 如果foo以小写字母开头,则假定它是消息发送,除非解析器之前已经看到foo的赋值,在这种情况下它被视为变量解引用。 (请注意,分配只需要解析,而不是执行; if false then foo = nil end完全没问题。)
  2. 如果Foo以大写字母开头,则将其视为变量(或相当不变)的解除引用,除非您传递参数列表(即使是空的),在这种情况下,它将被视为消息发送。
  3. 在这种情况下,RuntimeError被视为消息发送,因为它有一个参数列表:"must have a thing!"。当然,这是因为Ruby的另一个特点,即它允许你在参数列表周围省略括号,只要它是明确的。

    IOW:整个事情大致被解释为

    self.RuntimeError("must have a thing!")