因此,此方法有时会返回Resource类的实例,有时会返回“true”。
似乎我通过添加return关键字“修复”了这个问题,但我不太清楚它为什么会在第一时间发生。我使用RubyMine的调试器逐步完成了代码,在这两种情况下,它似乎遵循相同的路径,但它返回了不同的值。
我刚刚开始用Ruby编写代码,所以这对我来说都是个谜。
似乎只有在验证传递时才会出现问题。
即使这是固定的,我想澄清它为什么有效,或者为什么它首先不起作用。
这是有问题的方法:
def self.create_or_update(attributes = nil, options = {}, &block)
if attributes.is_a?(Array)
attributes.collect { |attr| create_or_update(attr, options, &block) }
else
begin
object = Resource.find_by_article_id(attributes[:article_id])
object.update_attributes!(attributes, options)
rescue
object = new(attributes, options, &block)
ensure
object.save
return object # for some reason, if you just leave out the "return" keyword, sometimes it returns "true" instead of an instance of the Resource class.. ??????
end
end
end
因此,经过一些调试并与我的主管交谈,我们已经弄清楚为什么会产生奇怪的行为。
'ensure'中的最后一个语句未被视为返回值,即使它是该方法中要处理的最后一个语句。实际被视为返回值的是来自 object.update_attributes的返回值!(属性,选项)
所以基本上......
def method
true
ensure
false
end
此方法返回 true ,这似乎违反直觉,因为“false”最后执行。
它似乎是语言规范/方法返回值的不一致,不是吗?
答案 0 :(得分:1)
首先,提示:我不会使用rescue
而不指定您要捕获的异常。这可能会导致各种各样的问题。
此方法返回不同值的原因是在ruby方法中,返回执行的最后一个语句的值。
http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Method_Calls#Return_Values
在您的代码中,您有条件,也有救援和保证。根据您最终输入的代码部分,将返回不同的值。例如,attributes.collect
将返回与new
如果您将对象放在方法的最后一行:
def self.create_or_update(attributes = nil, options = {}, &block)
if attributes.is_a?(Array)
..
else
begin
..
end
end
object
end
然后将始终返回对象。
答案 1 :(得分:1)
正如Kieran Andrews所说,有一件事是if和else返回不同的东西,虽然collect应该返回一个数组。
另一件事是如果记录不存在,对象是nil,那么nil.update_attributes!将引发异常,很容易判断对象是否为nil而不是catch异常。如果update_attributes!提出异常,你只是“新”而不做其他事情?如果验证失败,“新”可以保证“新”是有效的,这是你想要的吗?
如果记录不存在则“new”很容易理解,但我不确定是否update_attributes!失败也需要“新的。”
最后,如果
object.update_attributes!(attributes, options)
成功,不必“object.save”。
答案 2 :(得分:0)
因此,经过一些调试并与我的主管交谈,我们已经弄清楚为什么会产生奇怪的行为。
'ensure'中的最后一个语句未被视为返回值,即使它是该方法中要处理的最后一个语句。实际被视为返回值的是来自 object.update_attributes的返回值!(属性,选项)
所以基本上......
def method
true
ensure
false
end
此方法返回 true ,这似乎违反直觉,因为“false”最后执行。