Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to rescue model transaction and show the user an error?

So imagine you have 2 models, Person and Address, and only one address per person can be marked as 'Main'. So if I wanna change a person's main address, I need to use a transaction, to mark the new one as main and unmark the old one. And as far as I know using transactions in controllers is not good so I have a special method in model, thats what I've got:

AddressesController < ApplicationController  def update   @new_address = Address.find(params[:id])   @old_address = Address.find(params[:id2])   @new_address.exchange_status_with(@old_address)         end end 

Model:

class Address < ActiveRecord::Base   def exchange_status_with(address)     ActiveRecord::Base.transaction do      self.save!      address.save!     end        end end 

So thequestion is, if the transaction in the model method fails, I need to rescue it and notify the user about the error, how do I do that? Is there a way to make this model method return true or false depending on whether the transaction was successful or not, like save method does?

I probably could put that transaction in the controller and render the error message in the rescue part, but I guess its not right or I could put that method in a callback, but imagine there is some reason why I cant do that, whats the alternative?

PS dont pay attention to finding instances with params id and id2, just random thing to show that I have 2 instances

like image 544
NoDisplayName Avatar asked Jun 14 '14 09:06

NoDisplayName


People also ask

What happens if in a begin rescue block the rescue code has an error?

The code between “begin” and “rescue” is where a probable exception might occur. If an exception occurs, the rescue block will execute. You should try to be specific about what exception you're rescuing because it's considered a bad practice to capture all exceptions.

How do you rescue all exceptions in Ruby?

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 does rescue work in Ruby?

For each rescue clause, the raised Ruby exception is compared against each parameter and the match succeeds if the exception in the clause is the same as or a superclass of the thrown exception. If the thrown Ruby exception does not match any of the specified exception types, the else block gets executed.

How do you handle exceptions in Rails?

Exception handling in Ruby on Rails is similar to exception handling in Ruby. Which means, we enclose the code that could raise an exception in a begin/end block and use rescue clauses to tell Ruby the types of exceptions we want to handle.


Video Answer


1 Answers

def exchange_status_with(address)   ActiveRecord::Base.transaction do    self.save!    address.save!   end rescue ActiveRecord::RecordInvalid => exception   # do something with exception here end 

FYI, an exception looks like:

#<ActiveRecord::RecordInvalid: Validation failed: Email can't be blank> 

And:

exception.message # => "Validation failed: Email can't be blank" 

Side note, you can change self.save! to save!


Alternate solution if you want to keep your active model errors:

class MyCustomErrorClass < StandardError; end  def exchange_status_with(address)   ActiveRecord::Base.transaction do    raise MyCustomErrorClass unless self.save    raise MyCustomErrorClass unless address.save   end rescue MyCustomErrorClass   # here you have to check self.errors OR address.errors end 
like image 93
apneadiving Avatar answered Sep 18 '22 09:09

apneadiving