UPDATED I’m using Devise 1.4.9 for authentication and my Devise-generated User model doesn’t seem to be catching the exceptions being thrown by the DB when I try to create a new user with an email address that already exists in the DB. After following cicloon’s suggestion (see response below), my code to create a new user is…
class Api::RegistrationsController < Api::BaseController
respond_to :json
def create
user = User.new(params[:user])
user.ensure_authentication_token!
if user.valid?
user.save
render :json=> user.as_json(:auth_token=>user.authentication_token, :email=>user.email, :user_id=>user.id), :status=>201
return
else
warden.custom_failure!
render :json=> user.errors, :status=>422
end
end
end
The Devise-generated migration includes an index for the email attribute, including uniqueness validation…
add_index :users, :email, :unique => true
And here’s the user model…
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :token_authenticatable
attr_accessible :email, :password, :password_confirmation, :remember_me, :authentication_token
validates_uniqueness_of :email
def ensure_authentication_token!
reset_authentication_token! if authentication_token.blank?
end
def as_json(options={})
super(:only => [:email, :authentication_token, :id])
end
end
…I would like the database to raise an error during save if the specified email address already existed in the DB, have Rails catch it and execute the else block of code to return a 422 and description of the problem. It doesn’t, instead I get an SQLException error and a crash…
ActiveRecord::StatementInvalid (SQLite3::ConstraintException: constraint failed: INSERT INTO "users" ("authentication_token", "created_at", "current_sign_in_at", "current_sign_in_ip", "email", "encrypted_password", "last_sign_in_at", "last_sign_in_ip", "remember_created_at", "reset_password_sent_at", "reset_password_token", "sign_in_count", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)):
app/models/user.rb:33:in `ensure_authentication_token!'
app/controllers/api/registrations_controller.rb:7:in `create'
How can I get my code to return a 422 with a description of the error?
Thanks so much in advance for your wisdom!
I read your post again, now I see what’s happening there. You have a database index, and Rails is not aware of that, so when you make @user.save the database throws an exception which is not captured Rails side.
That said, you have two choices:
1.) Capture the exception in Rails:
2.) Add the validation to your model and check for user.valid?:
On your user model:
On your controller: