2010-08-26 2 views
1
class State < ActiveRecord::Base 
    validates_uniqueness_of :identifier 
end 

Supposons maintenant qu'il existe deux processus en cours qui peuvent éventuellement insérer deux de ces enregistrements simultanément. Le passager est un bon exemple. Voici un artificiel:Empêcher plusieurs processus d'enregistrement actifs d'insérer des enregistrements en double

State.find_by_identifier("UNIQ").delete rescue nil 
while Time.now < Time.now.change(:hour => 17, :min => 00, :sec => 15) 
    sleep 0.001 
end 
ActiveRecord::Base.transaction do 
    s = State.new;s.identifier = "UNIQ" 
    s.save! 
end 
s.valid? 

L'idée est que nous changeons les valeurs de temps pour être légèrement dans le futur. Ensuite, copiez/collez le tout dans deux consoles différentes.

Le but ultime est de les "libérer" en même temps. Ce qui se produit? Ils réussissent tous deux à créer un nouvel objet Etat, et tous deux retournent faux à la fin.

Alors, comment empêcher cela de se produire?

Pour ce que ça vaut, j'utilise MySQL et la table est InnoDB.

Répondre

0

Vous utilisez des méthodes d'aide #find_or_create, en plus de la validation correcte et un index unique au niveau de la base de données:

# In a migration 
add_index :states, :identifier, :unique => true 

class State < ActiveRecord::Base 
    validates_uniqueness_of :identifier 
end 

State.find_or_create_by_identifier("UNIQ") 

qui fonctionnera avec un adaptateur.

+0

Je me demande pourquoi cette réponse a été rejetée? Il semble complet et garantit que rien ne dépasse jamais les validations du serveur de base de données. –

Questions connexes