我有一系列嵌套的 each
循环遍历卡片列表。这些循环调用其他子函数,这些子函数测试是否满足某些条件才能继续。
def card_handler
cards.each do |card|
#some non-relevant code is here on my end
already_sent?
end
end
def already_sent?
# allows for checking if different emails have been sent on the same card
if list_action == 147
a_s_helper(p1_label)
elsif list_action == 146
a_s_helper(p2_label)
elsif list_action == 145
a_s_helper(p3_label)
end
end
def a_s_helper(label)
if card::card_labels.include? label
# if the card already has the label, I want to log the error and return all the way to the next card in the iteration
puts '\n Order info: \n id: #{id} \n Email already sent'
next
# doesn't work
else
real_id?
end
end
就像我在a_s_helper中的评论中所说的,如果卡已经有了标签,我希望记录错误并返回迭代中的下一张卡。我从当前设置中得到一个“无效的下一个”错误。
有没有退票的办法 next
返回到父函数或循环?
2条答案
按热度按时间vbkedwbf1#
next
仅在循环的直接上下文中有效。一旦您调用了一个方法,您就不再直接处于该循环上下文中。您不能使用next来像这样短路外回路。您有两个选择:
从 predicate 函数返回状态(这是您应该从 predicate 执行的操作!)并在此基础上短路回路,或
使用ruby的
catch...throw
构造(它不是它的raise/rescue异常处理程序,而是类似于块范围的goto语句)选项1:返回状态。依我看,这是最合适的方法。 predicate 方法(以?结尾的方法)通常应该返回布尔值并且是幂等的(也就是说,应该没有副作用,比如记录语句)。他们习惯于问是/否的问题。理想情况下,根据这个问题决定做什么应该超出他们的范围。
这会导致助手向循环返回true或false值,循环可以决定记录消息并转到下一次迭代。
备选案文2:
catch...throw
```def card_handler
cards.each do |card|
# Put all your code that should nomally run inside the catch block. If
# the message :email_sent is thrown, then Ruby will zip up the stack and
# resume execution at the end of the block. This will skip any unexecuted
# code in the block, essentially terminating the execution.
catch :email_sent do
already_sent?
end
end
end
def already_sent?
...
end
def a_s_helper(label)
...
throw :email_sent if card::card_labels.include? label
...
end
vbopmzt12#
我想向未来看到这个问题的人展示一下,我是如何实现从@chris heald那里得到的解决方案的。我把它做得更紧凑了一点。这就是我最终使用的代码: