Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to move a rescue block to a method

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.

like image 892
Ajay Avatar asked Jun 30 '15 09:06

Ajay


People also ask

Can we use rescue without begin?

The method definition itself does the work of begin , so you can omit it. You can also do this with blocks. Now, there is one more way to use the rescue keyword without begin .

What is a rescue block?

A rescue block can be what saves you from falling and injuring yourself, as they protect you from falling to the ground when working at height. The synthetic rope or cable that is wrapped around the reel of the block works like a retractable lifeline, which suspends you in the air in the event of a fall.

What does Ruby Rescue do?

A raised exception can be rescued to prevent it from crashing your application once it reaches the top of the call stack. In Ruby, we use the rescue keyword for that. When rescuing an exception in Ruby, you can specify a specific error class that should be rescued from.

How do you use try catch in Ruby?

Ruby Internal try catch (raise and rescue) In case exceptions happen in the begin block it will halt and control will go between rescue and end, and we can return a valid message for the user in case of exceptions. Every time for a rescue statement Ruby checks and compares the exception raised for each parameter.


2 Answers

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 
like image 129
A Fader Darkly Avatar answered Sep 27 '22 17:09

A Fader Darkly


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

like image 20
Piotr Kruczek Avatar answered Sep 27 '22 15:09

Piotr Kruczek