7

I have the following method in one of my models to save a user record:

def save_user(params)
  begin 
    save_user_details(params)
  rescue ActiveRecord::RecordInvalid => ex  
    { success: false, errors: ex.messages }
  rescue Exception => ex
    Rails.logger.info(ex.message)
    Rails.logger.info(ex.backtrace.join(‘\n’)
    { success: false, errors: ’Some error occurred.}
  end
end

We can see that the rescue block is heavy and such block is common in other actions as well. So I gave a thought to refactor this and move the rescue block to a separate function. I want to implement something like this:

def save_user(params)
  begin 
    save_user_details(params) # my method to save the details 
    handle_the_exception # not sure how to implement this 
  end
  def handle_the_exception
    # How to handle here ? 
  end

Any thoughts on an implementation as in above will be a great help.

sawa
  • 165,429
  • 45
  • 277
  • 381
Ajay
  • 4,199
  • 4
  • 27
  • 47
  • 7
    **DO NOT** rescue `Exception`. http://stackoverflow.com/questions/10048173/why-is-it-bad-style-to-rescue-exception-e-in-ruby?lq=1 – Sergio Tulentsev Jun 30 '15 at 09:39
  • Thanks for the direction ! Great Help indeed :) @SergioTulentsev – Ajay Jun 30 '15 at 09:51
  • `save_user` looks like it belongs in your controller. In that case, you could register an [exception handler](http://guides.rubyonrails.org/action_controller_overview.html#rescue). – Stefan Jun 30 '15 at 10:02

2 Answers2

23

Something like this:

def save_user(params)
  handle_exception do 
    save_user_details(params) # my method to save the details 
  end
 end

 def handle_exception(&block)
   begin
     block.call
   rescue => ex
     Rails.logger.info(ex.message)
     Rails.logger.info(ex.backtrace.join("\n")
     { success: false, errors: "Some error occurred."}
   end
 end

In IRB:

2.2.0 :021 > def handle_exception(&block)
2.2.0 :022?>   begin
2.2.0 :023 >     block.call
2.2.0 :024?>   rescue => ex
2.2.0 :025?>     puts ex.inspect
2.2.0 :026?>     puts "handled"
2.2.0 :027?>   end
2.2.0 :028?> end
 => :handle_exception 
2.2.0 :029 > handle_exception do
2.2.0 :030 >   raise "hell"
2.2.0 :031?>   puts "Don't reach me"
2.2.0 :032?> end
#<RuntimeError: hell>
handled
 => nil 
A Fader Darkly
  • 3,516
  • 1
  • 22
  • 28
3

You could try doing

def save_user(params)
  save_user_details(params)
rescue => e
  handle_exception(e)
end

def handle_exception(error)
  Rails.logger.info(error.message)
  Rails.logger.info(error.backtrace.join(‘\n’))
  { success: false, errors: error.messages }
end

And here's why you shouldn't rescue Exception

Community
  • 1
  • 1
Piotr Kruczek
  • 2,384
  • 11
  • 18