I have a Ticket
model with basic uniqueness validation on a string attribute ticket_number
validates :ticket_number, uniqueness: t
@Yule answer was very helpful , it explained Why this happened and that adding database level constraint will prevent it.
The docs says, this will throw an ActiveRecord::RecordNotUnique
exseption which i don't want the users to see ofcourse, so here is exactly how to apply the workaround suggested by @Yule:
Add an index on the attribute
add_index(:tickets, :ticket_number, :unique => true)
Adjust the controller#create
action to catch the db exception:
def create
@ticket = Ticket.new(ticket_params)
if @ticket.save
flash[:success] = 'Ticket was successfully created.'
else
render action: 'new'
end
#catch the exception
rescue ActiveRecord::RecordNotUnique
flash[:danger] = 'The ticket number you entered is already taken !'
render action: 'new'
end
Same should be done for controller#update action ofcourse
This is very uncommon and you're probably very unlucky that it has, it is possible.
Read: https://github.com/rails/rails/blob/master/activerecord/lib/active_record/validations/uniqueness.rb#L165
Consider the following: User A submits form
All this has to happen within milliseconds but it is technically possible.
I'd suggest adding a constraint at the database level (primary key).