Yesterday in mailing list of russian RoR group we have discussed following problem. MySQL database has unique index and model has validates_uniqueness_of constraint. Do we need to handle MySQL server exceptions or RoR’s validation will be enough?
I think we need, but to be sure I decided to make test. First, I created table with unique index:
def self.up
create_table :customers do |t|
t.column :name, :string
end
add_index :customers, :name, :unique => true
end
def self.down
drop_table :customers
end
end
Then I wrote following model:
validates_presence_of :name, :if => lambda { |customer|
unless @@created
@@created = true
Customer.create(:name => customer.name)
end
true
}
validates_uniqueness_of :name
@@created = false
end
You can see two validation rules: one is uniqueness, which is the our primary goal. Second rule’s task is to create second customer between validation and insertion of first. Validations are processed in postorder, therefor validates_presence_of is going first. Now I’ve started script/console and typed:
You can find log file below. I think, you don’t need any comments.
Note: You right, this is broken logic, but I used it only to show what will be if two processes will insert record with the same name. You can replace code inside :if with sleep 10 and run two consoles to reproduce exception.
Русский
English