Let's say I have an online bookstore whose data model looks like this:

Before creating a new order, I want to make sure that there are enough items in stock, so I have this method
def ensure_enough_in_stock errors.add(:quantity, "not enough in stock") if quantity > book.stock end
To make sure this method is called before saving to the database, I use validate:
validate :ensure_enough_in_stock, :on => create
So, to summarize when I create an order:
- verification method called
- the new order is written to the database (if the check passed)
What happens if between 1. and 2. another process (concurrent access, another thread, ...) modifies the stock attribute of the same book? Is an exception thrown?
More generally, how to handle cases when something happens between validation and storage in the database?
I think I should put validation in the database, but I don't know what impact this would have on performance. Is there any reasonable way to handle this situation?
EDIT
Transaction locking, as described here, prevents write access to the stock, but what happens if I also have a “published” attribute in the model book that can take the value “public” or “private”, and then I want to make sure that you You cannot buy a book that is private.
But just as the stock value can be changed by an external process, the published value can also be changed: in this case, blocking will not be of any help, is it?
