方法有时会返回true,有时会返回对象的实例

时间:2014-01-29 05:42:16

标签: ruby-on-rails ruby rails-activerecord

因此,此方法有时会返回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”最后执行。

它似乎是语言规范/方法返回值的不一致,不是吗?

3 个答案:

答案 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”最后执行。