您可以将"next"传递回调用当前函数的函数吗?



我有一系列嵌套的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返回到父函数或循环?

next仅在循环的直接上下文中有效。一旦您调用了一个方法,您就不再直接处于该循环上下文中。你不能像这样用next来短路外环。

你有几个选择:

  1. 从谓词函数返回状态(这是您应该做的,从谓词!(并根据这些状态缩短循环,或者
  2. 使用Ruby的catch...throw构造(它不是其引发/救援异常处理程序,而是类似于块范围的GOTO语句(

选项1:返回状态。这是最合适的方法,IMO.谓词方法(以?结尾的方法(通常应该返回布尔值并且是幂等的(也就是说,应该没有副作用,比如记录语句(。它们通常被用来问是/否的问题。根据这个问题来决定该做什么,理想情况下应该超出他们的范围。

def card_handler
cards.each do |card|
#some non-relevant code is here on my end
if already_sent?
puts 'n Order info: n id: #{id} n Email already sent'
next
end
end
end

def already_sent?
case list_action
when 145
a_s_helper(p3_label)
when 145
a_s_helper(p2_label)
when 147
a_s_helper(p1_label)
end
end
def a_s_helper(label)
card::card_labels.include? label
end

这会导致您的助手向循环返回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

您可能会倾向于使用选项2,因为它需要对方法构造进行不那么仔细的控制,但它与流控制的异常非常接近,流控制被广泛认为是反模式(它本质上是一个稍微花哨一点的GOTO,因使代码难以读取和调试而臭名昭著(。如果你可以简单地从你的助手那里返回一个状态,并根据它决定是否继续循环,你应该这样做

我想向未来看到这个问题的人展示我是如何最终实现@Chris heald提供的解决方案的。我把它做得紧凑一点。这是我最终使用的代码:

def card_handler
cards.each do |card|
real_id?
puts "real_id? : #{real_id?}"
next if !(real_id?)
needs_email?
puts "needs_email? : #{needs_email?}"
next if !(needs_email?)
get_email_info
end
end

def needs_email?
case list_action
when 147
!(card::card_labels.include? p1_label::id)
when 146
!(card::card_labels.include? p2_label::id)
when 145
!(card::card_labels.include? p3_label::id)
else
false
end
end
def real_id?
id != 0 ? true : false
end
def get_email_info
#more stuff
end

相关内容

  • 没有找到相关文章

最新更新