我在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>>
答案 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
),默认接收器为空参数列表“。
这种含糊不清的解决方法如下:
foo
以小写字母开头,则假定它是消息发送,除非解析器之前已经看到foo
的赋值,在这种情况下它被视为变量解引用。 (请注意,分配只需要解析,而不是执行; if false then foo = nil end
完全没问题。)Foo
以大写字母开头,则将其视为变量(或相当不变)的解除引用,除非您传递参数列表(即使是空的),在这种情况下,它将被视为消息发送。在这种情况下,RuntimeError
被视为消息发送,因为它有一个参数列表:"must have a thing!"
。当然,这是因为Ruby的另一个特点,即它允许你在参数列表周围省略括号,只要它是明确的。
IOW:整个事情大致被解释为
self.RuntimeError("must have a thing!")