当用作回调时,“return”和“break”在 Ruby 块内无用吗?

发布于 2024-10-12 08:27:34 字数 1045 浏览 3 评论 0原文

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

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

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

当使用块时这样的话,breakreturn还有用吗?我这样问是因为通常在块中, 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夜巴黎 2024-10-19 08:27:34

实际上这很有趣......

当您在 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 相同(因为它正常方法)。

一般来说,块中的next会从该块“返回”。

普通块的具体行为是:

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

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

value = [1,2,3,4].each do |i|
  next 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

重要的是 nextbreak 不仅仅适用于迭代器,尽管它们的语义设计得像 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:

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

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

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:

  • When you call next, you are skipping the rest of the block, and returning control to the method that invoked the block.
  • When you call 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:

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

In this case, value will be [1,2,3,4], the normal return value of the each method, and the output will be:

1
3
4

In the case of break:

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

In this case, the value will be nil, since the break also immediately returned from the each method. You can force a return with a specific value by using break n, which will make value the same as n. The output in the above case will be:

1

The important thing is that next and break do not just apply to iterators, although their semantics are designed to behave like their equivalents in C in the case of iterators.

人生戏 2024-10-19 08:27:34

Ruby 块中的 return 操作取决于该块是使用 Proc.new 还是 lambda 构造的。

我建议您阅读有关其他 Stack Overflow 问题的最高评价答案:何时使用 lambda,何时使用 Proc.new?

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

在这种回调的上下文中调用 return 仅当这也有意义时才有意义(显然没有):

class Foo
  return "bar"
end

The operation of return within Ruby blocks depends whether the block was constructed with Proc.new or lambda.

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):

class Foo
  return "bar"
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文