2015-11-04 88 views
4

我希望能够从调用方法中返回,同时仍在调用方法内。Ruby:从调用方法返回

例子:

def calling_method 
    # stuff 
    called_method 
    # more stuff 
end 

def called_method 
    # stuff 
    return_from_caller if foo # << I would like to return from calling_method 
    # more stuff 
end 

有没有一种简单的方法来实现这一目标?

的“脏”的办法,我用的那一刻是这样的:

def calling_method 
    # stuff 
    called_method and return 
    # more stuff 
end 

def called_method 
    # stuff 
    return false if foo 
    # more stuff 
end 

但是,这并不完全令人满意,因为我在调用的方法做了and return

+0

Ruby,像其他语言一样,获取返回语句时结束该方法。您可以在内容中设置一个变量,并在此方法结束时返回。 – gFontaniva

+0

我真的不明白你的评论。你能提供一个代码示例吗? – Mat

+0

如果语义上有意义,您也可以引发异常。 – Felix

回答

3

我想,你不能那样做。

你可以做到这一点(至少我现在能想到的)的唯一方法是,通过使用你所谓的dirty这样做。

实际上,do_something and return是您在Ruby/Rails代码中看到的一种非常常见的模式/用例。

因此,国际海事组织,这是要走的路:

def calling_method 
    # stuff 
    called_method and return 
    # more stuff 
end 
+0

谢谢。事实上,你告诉我这是常见的让我有点担心。我会等几分钟,看看是否有更好的答案弹出,然后upvote并选择你的答案,如果没有。 – Mat

+0

同时,你可以看看这篇文章:http://blog.arkency.com/2014/07/4-ways-to-early-return-from-a-rails-controller/和http: //stackoverflow.com/questions/5539106/rails-render-and-exit-immediately和....只是谷歌它:) –

+1

第一个链接确认它确实可以做到这一点,所以再次感谢:) – Mat

1

像这样的事情只可能有块,其中有直接返回其产生块方法的能力。考虑下面这个例子:

# You don't need to specify &block here, it works the same if you omit it 
# I added it for clarity 
def calling_method(&block) 
    puts 'before' 
    puts yield 
    puts 'after' 
end 

现在,你可以调用calling_method不同的块和观察方法的行为:

首先,我们用一个普通块返回一个简单的值称之为

calling_method { 3 } 
# before 
# 3 
# after 
# => nil 

现在,我们尝试,如果您使用next关键字块内发生了什么:

calling_method { next 23 } 
# before 
# 23 
# after 
# => nil 

对于procs,next关键字实际上是return。它结束proc的执行并返回给定的值(默认情况下为nil)。

最后,我们来看看,当我们在该块使用break会发生什么:

p calling_method { break 23 } 
# before 
# => 23 

当您使用Ruby中break关键字,什么情况是,PROC回报和其产生的方法块也会立即返回给出break关键字的值。因此,如果您可以重新编写逻辑,以便您的called_method中当前定义的行为可以在块中重写并传递到calling_method,那么您可以控制该块的返回行为。

如果您必须调用实际方法,那么called_method and return技术是唯一的方法。

0

这应该工作。从lambda返回应该继续流程的其余部分

def calling_method 
    # stuff 
    lambda { called_method } 
    # more stuff 
end 
def calling_method 
    # stuff 
    lambda { called_method } 
    # more stuff 
end