当用作回调时,“return”和“break”在 Ruby 块内无用吗?
在Rails中,块可以用作回调,例如:
class User < ActiveRecord::Base
validates_presence_of :login, :email
before_create {|user| user.name = user.login.capitalize
if user.name.blank?}
end
当使用块时这样的话,break
和return
还有用吗?我这样问是因为通常在块中, break
将跳出循环,而 return
将从封闭方法返回。但在回调上下文中,我无法理解这意味着什么。
Ruby 编程语言 建议 return
可能会导致 LocalJumpError
但我无法在 Rails 回调中重现此问题。
编辑:使用以下代码,我预计会出现 LocalJumpError
,但 return
所做的只是停止回调执行的其余部分。
class User < ActiveRecord::Base
validates_presence_of :login, :email
before_create do |user|
return
user.name = user.login.capitalize
end
In Rails, blocks can be used as callbacks, e.g.:
class User < ActiveRecord::Base
validates_presence_of :login, :email
before_create {|user| user.name = user.login.capitalize
if user.name.blank?}
end
When a block is used like this, is there any use for break
and return
? I'm asking because normally in a block, break
will break out of the loop, and return
will return from the enclosing method. But in a callback context, I can't get my head round what that means.
The Ruby Programming Language suggests that return
could cause a LocalJumpError
but I haven't been able to reproduce this in a Rails callback.
Edit: with the following code I'd expect a LocalJumpError
, but all the return
does is stop the rest of the callback executing.
class User < ActiveRecord::Base
validates_presence_of :login, :email
before_create do |user|
return
user.name = user.login.capitalize
end
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
实际上这很有趣......
当您在 Rails 3 中使用 before_create 时,我们会获取您提供给我们的块或 lambda 并将其转换为方法。然后,我们使用当前的 ActiveRecord 对象调用该方法,以向后兼容旧的 Rails 方法。
因此,以下内容相当于您的代码片段:
由于这种行为,您可以从块中调用 return,并且其行为与普通方法中的 return 相同(因为它是正常方法)。
一般来说,块中的
next
会从该块“返回”。普通块的具体行为是:
next
时,您将跳过该块的其余部分,并将控制权返回给调用该块的方法。break
时,您将跳过该块的其余部分,并立即从调用该块的方法返回。您可以在普通迭代器中看到这种行为:
在这种情况下,
value
将是[1,2,3,4]
,即each 的正常返回值
方法,输出将为:在中断的情况下:
在这种情况下,
value
将为nil
,因为break 也立即从
each
方法返回。您可以使用break n
强制返回特定值,这将使value
与n
相同。上述情况的输出将是:重要的是
next
和break
不仅仅适用于迭代器,尽管它们的语义设计得像 C 中的等效项一样对于迭代器来说。Actually it's kind of interesting...
When you use before_create in Rails 3, we take the block or lambda that you give us and convert it into a method. We then invoke the method with the current ActiveRecord object, for backwards compatibility with the old Rails approach.
As a result, the following is equivalent to your snippet:
Because of this behavior, you can call return from the block, and it will behave the same as a return in a normal method (because it is a normal method).
In general,
next
in a block "returns" from the block.The specific behavior of normal blocks is:
next
, you are skipping the rest of the block, and returning control to the method that invoked the block.break
, you are skipping the rest of the block, and also immediately returning from the method that invoked the block.You can see that behavior in normal iterators:
In this case,
value
will be[1,2,3,4]
, the normal return value of theeach
method, and the output will be:In the case of break:
In this case, the
value
will benil
, since thebreak
also immediately returned from theeach
method. You can force a return with a specific value by usingbreak n
, which will makevalue
the same asn
. The output in the above case will be:The important thing is that
next
andbreak
do not just apply to iterators, although their semantics are designed to behave like their equivalents in C in the case of iterators.Ruby 块中的
return
操作取决于该块是使用Proc.new
还是lambda
构造的。我建议您阅读有关其他 Stack Overflow 问题的最高评价答案:何时使用 lambda,何时使用 Proc.new?
在这种情况下,该块具有使用
Proc.new
创建的块的属性。在这种回调的上下文中调用
return
仅当这也有意义时才有意义(显然没有):The operation of
return
within Ruby blocks depends whether the block was constructed withProc.new
orlambda
.I recommend you read the highest rated answer on this other Stack Overflow question: When to use lambda, when to use Proc.new?
In this case, the block has the properties of one created with
Proc.new
.Calling
return
in the context of that kind of callback would only make sense if this also made sense (which it obviously doesn't):