Search code examples
ruby-on-railsrubyreturnbreak

Best way to break and return a value


I have a method that's nested within a couple other methods, and I want this method to break from all recursive methods with a returned error. For instance, if I have pay_order being called here:

class API::StripeController < ApiController
  def my_api_action
    # ...
    order = create_order
    pay_order(order, token)
    # do things if payment is successful
  end
end

And pay_order is defined as:

def pay_order(order, token)
  begin
    order.pay(source: token)
  rescue Stripe::CardError => e
    break e
  end
end

How do I break out of all parent methods and return the card error coming from the failed payment? I need something like break and return e or return e and break. But I know both the break and return statements immediately return, so I can't chain them (I don't think).

I could just add return statements to each function being called, but I plan on using this method in lots of places, and don't plan on ever needing it to behave differently, so I'm looking for the most reusable way to write it.


Solution

  • Why do you rescue inside the pay_order method? I'd rescue on the outer loop. Given the following:

    def method_a
      10.times do |loop_a|
        method_b
      end
    end
    
    def method_b
      5.times do |loop_b|
        pay_order
      end
    end
    
    def pay_order
      ...
    end
    

    I'd rescue inside method_a, for example:

    def method_a
      10.times do |loop_a|
        method_b
      end
    rescue Stripe::CardError => e
      # do whatever. no need to break
    end
    

    All the loops are "broken" automatically by the raising of the exception.

    If you want to do something with the exception inside the pay_order method, then I would suggest to rescue and raise again:

    def pay_order
      order.pay
    rescue Stripe::CardError => e
      # do your stuff
      raise e
    end