4

在 Rails 中,块可以用作回调,例如:

class User < ActiveRecord::Base
  validates_presence_of :login, :email

  before_create {|user| user.name = user.login.capitalize
    if user.name.blank?}
end

像这样使用块时,breakand有什么用return吗?我问是因为通常在一个块中,break会跳出循环,并return从封闭方法返回。但是在回调上下文中,我无法理解这意味着什么。

Ruby 编程语言建议这return可能会导致 aLocalJumpError但我无法在 Rails 回调中重现这一点。


编辑:我希望使用以下代码LocalJumpError,但return所做的只是停止其余的回调执行。

class User < ActiveRecord::Base
  validates_presence_of :login, :email

  before_create do |user|
    return
    user.name = user.login.capitalize
end
4

2 回答 2

10

其实有点意思。。。

当您在 Rails 3 中使用 before_create 时,我们会将您提供给我们的块或 lambda 转换为方法。然后我们使用当前的 ActiveRecord 对象调用该方法,以向后兼容旧的 Rails 方法。

因此,以下内容等同于您的代码段:

class User < ActiveRecord::Base
  validates_presence_of :login, :email

  before_create do
    self.name = login.capitalize if name.blank?
  end
end

由于这种行为,您可以从块中调用 return,它的行为与普通方法中的 return 相同(因为它普通方法)。

通常,continue在一个块中从块“返回”。

普通方块的具体行为是:

  • 当您调用 时continue,您将跳过该块的其余部分,并将控制权返回给调用该块的方法。
  • 当您调用 时break,您将跳过该块的其余部分,并立即从调用该块的方法返回。

您可以在普通迭代器中看到这种行为:

value = [1,2,3,4].each do |i|
  continue if i == 2
  puts i
end

在这种情况下,value将是方法[1,2,3,4]的正常返回值,each输出将是:

1
3
4

在中断的情况下:

value = [1,2,3,4].each do |i|
  break if i == 2
  puts i
end

在这种情况下,value将是nil,因为break也立即从该each方法返回。您可以使用 强制返回具有特定值的值break n,这将valuen. 上述情况下的输出将是:

1

重要的是,它continue不仅仅break适用于迭代器,尽管它们的语义被设计成在迭代器的情况下表现得像它们在 C 中的等价物。

于 2011-01-15T21:49:55.507 回答
3

Ruby 块内的操作return取决于块是用Proc.new还是构造的lambda

我建议您阅读另一个 Stack Overflow 问题上评分最高的答案:何时使用 lambda,何时使用 Proc.new?

在这种情况下,该块具有使用 创建的一个的属性Proc.new

只有在这也有意义的情况下,在这种回调的上下文中调用return才有意义(显然没有):

class Foo
  return "bar"
end
于 2011-01-15T21:23:28.990 回答