Something has been bothering me about model validation: how do I know that
the database has not changed in between when I validate my model's data, and
when it actually gets saved to the database? As a simple example, say I have
a User model like:
When this gets saved to the database, the validation code checks that there is
not already a row containing the same value for username as in our object.
The object is then saved to the database and everyone is happy. But what if
there is another user trying to register with the same username at the same
time? I am assuming that with load balancing situations is it possible that
two rails processes could try to save a User object at the same time. So
what happens if the User object in each process checks that its username is
unique, and then each User object does an insert into the database. Is the
uniqueness constraint not violated?
One option would be to have a database-level uniqueness constraint, but I've
heard that this is not the "rails way", and in any case, this is just a
simple example. In general the validation code could be arbitrarily complex.
The other option that I can see is to use a transaction around the save
operation, and define an after_save callback that re-validates the data in
the database. If (for the username example above) there is more than one
identical username, the after_save callback could throw an exception which
(as I understand it) would back out the transaction. Although if this is
done, perhaps it is not worth validating the model before saving it in the
first place, since we would catch any errors in after_save.
Is this the way that this problem is usually handled? Or am I seeing a
problem where one does not really exist?