Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rails 3.1: how can app handle different 'reasons' for ActiveRecord::RecordInvalid (for example, duplicate vs validation error)

In my app, I sometimes create a User on the fly, and a user's email must be a valid format, and be unique.

I would like to redirect to different places depending on WHICH validation caused the error to be raised: invalid format vs duplicate.

In my code I have

    begin
      user.save!
      flash[:notice] = "Created new user #{email} with password #{password}"

    rescue ActiveRecord::RecordInvalid => e
      flash[:alert] = "Failed to create account because #{e.message}"
      redirect_to SOMEPLACE
    end

If the email is invalid format (such as "user@example") e.message is "Validation failed: Email is invalid"

If the email already exists in the table, e.message is "Validation failed: Email has already been taken"

I hate the idea of parsing e.message text to determine the reason... is there a better way for a rescue handler to detect the underlying reason a ActiveRecord::RecordInvalid exception was thrown?

P.S. I know in THIS example I can simply check ahead for the email already existing before doing a save, but I'm trying to understand the general solution to detecting and acting on different validation failures throwing the same exception.

like image 829
jpw Avatar asked Mar 06 '12 21:03

jpw


1 Answers

The standard Rails way to do this is not to use the bang operator, which raises an exception, but to use the standard save method and check whether it returned true or false:

if @user.save
  flash[:notice] = "User created."
  redirect_to :action => :index
else
  flash[:alert] = "User could not be created."
  render :action => :new
end

And in your user creation view:

<% if @user.errors.any? %>
  <ul>
    <% @user.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
    <% end %>
  </ul>
<% end %>
like image 100
Veraticus Avatar answered Nov 15 '22 09:11

Veraticus