Вот краткий пример, технически здесь все еще есть условие гонки, хотя, если вы не видите сотен или тысяч созданий в секунду, это действительно не должно вызывать беспокойства, в худшем случае ваш пользователь получит ошибку уникальности, если два создания запущены втаким образом, что они оба выполняют поиск и возвращают ноль с одним и тем же Url
class Credit < ActiveRecord::Base
before_validation :create_code, :if => 'self.new_record?'
validates :code, :uniqueness => true
def create_code
self.code = code_generator
self.code = code_generator until Credit.find_by_code(code).nil?
end
end
Если вам абсолютно необходимо удалить случай условия гонки, когда два создания работают в тандеме, и оба запускают поиск с одинаковымcode и return nil, вы можете обернуть находку блокировкой таблицы, для которой требуется специфичный для БД SQL, или вы можете создать таблицу, в которой есть строка, используемая для блокировки с помощью пессимистической блокировки, но я бы не пошел так далеко, если бы вы не ожидали сотнисоздает в секунду, и вам абсолютно необходимо, чтобы пользователь никогда не видел ошибку, это выполнимо, в большинстве случаев просто избыточно.