ActiveRecord exceptions not rescued

Posted by zoopzoop on Stack Overflow See other posts from Stack Overflow or by zoopzoop
Published on 2011-01-06T16:56:02Z Indexed on 2011/01/08 11:53 UTC
Read the original article Hit count: 301

I have the following code block:

unless User.exist?(...)
  begin
    user = User.new(...)
    # Set more attributes of user
    user.save!
  rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique => e
    # Check if that user was created in the meantime
    user = User.exists?(...)
    raise e if user.nil?
  end
end

The reason is, as you can probably guess, that multiple processes might call this method at the same time to create the user (if it doesn't already exist), so while the first one enters the block and starts initializing a new user, setting the attributes and finally calling save!, the user might already be created. In that case I want to check again if the user exists and only raise the exception if it still doesn't (= if no other process has created it in the meantime).

The problem is, that regularly ActiveRecord::RecordInvalid exceptions are raised from the save! and not rescued from the rescue block. Any ideas?

EDIT:

Alright, this is weird. I must be missing something. I refactored the code according to Simone's tip to look like this:

unless User.find_by_email(...).present?
  # Here we know the user does not exist yet
  user = User.new(...)
  # Set more attributes of user
  unless user.save
    # User could not be saved for some reason, maybe created by another request?
    raise StandardError, "Could not create user for order #{self.id}." unless User.exists?(:email => ...)
  end
end

Now I got the following exception:

ActiveRecord::RecordNotUnique: Mysql::DupEntry: Duplicate entry '[email protected]' for key 'index_users_on_email': INSERT INTO `users` ...

thrown in the line where it says 'unless user.save'. How can that be? Rails thinks the user can be created because the email is unique but then the Mysql unique index prevents the insert? How likely is that? And how can it be avoided?

© Stack Overflow or respective owner

Related posts about ruby-on-rails

Related posts about exception