J'ai lu le Rails Guide et j'étais curieux, alors je l'ai touché. Ce mémo.
Lorsque M. A et M. B éditent le même dossier dans la demande, si M. A accède au même dossier exactement au même moment, M. A met à jour le dossier et ensuite M. B met à jour, M. B édite le contenu de M. A. Il sera écrasé sans confirmation. S'il s'agit d'une mise à jour avec le même attribut, et s'il s'agit d'un autre attribut, l'édition sera rembobinée, ce qui n'est pas une bonne situation.
Active Record fournit lock_version pour ce problème. lock_version ajoute une colonne à la table qui agit comme un compte d'historique d'édition pour cette instance, et en référençant sa valeur Si vous utilisez lock_version, vous pouvez générer une erreur dans les cas ci-dessus.
Pour l'utiliser, créez une colonne appelée lock_version dans la table.
t.integer :lock_version, default: 0
p1 = Memo.find(1)
p2 = Memo.find(1)
# => #<Memo id: 1, text: "hello", lock_version: 0>
Bien sûr, lock_version vaut 0 quand il est toujours appelé Puis mettez à jour p1.
p1.update(text:'good bye')
# => #<Memo id: 1, text: "good bye", lock_version: 1>
SQL
(0.3ms) BEGIN
Memo Update (13.4ms) UPDATE `memos` SET `text` = 'good bye', `lock_version` = 1 WHERE `memos`.`id` = 1 AND `memos`.`lock_version` = 0
(3.9ms) COMMIT
look_version a été réécrit à 1.
Vous pouvez également voir que la condition SQL pour la mise à jour a lock_version = 0
.
Ensuite, mettons à jour p2. La lock_version de l'instance p2 reste 0 car elle n'a pas été rechargée.
p2.update(text:'say hello')
# => ActiveRecord::StaleObjectError (Attempted to update a stale object: Memo.)
SQL
(0.7ms) BEGIN
Memo Update (1.0ms) UPDATE `memos` SET `text` = 'say hello', `lock_version` = 1 WHERE `memos`.`id` = 1 AND `memos`.`lock_version` = 0
(2.4ms) ROLLBACK
Vous obtenez une erreur. Je ne pense pas que SQL lui-même sera généré même si une erreur est exécutée, il semble donc qu'une erreur soit renvoyée avec le déclencheur indiquant qu'aucune ligne n'affecte les rails. Je ne lirai pas la source cette fois, donc si vous la lisez, partagez-la!
Comme pour RailsApi, mettons lock_version comme paramètre caché dans le formulaire. Sans cela, le backend ne pourra pas comparer lock_version et ne générera pas d'erreur.
<input type="hidden" value="2" name="memo[lock_version]" id="memo_lock_version">
J'ai ajouté ce qui précède, ouvert deux onglets pour modifier le même enregistrement et mis à jour chacun, et celui qui a mis à jour plus tard a obtenu une erreur en toute sécurité.
Après cela, traitons l'erreur comme décrit dans Rails Api. Il existe différentes manières de gérer cela.
――Si deux personnes ont modifié des attributs différents, mettez-les à jour dans l'ordre et lorsqu'elles modifient le même attribut, affichez-le à l'écran et confirmez avec l'utilisateur.
Et. Je me demande si cette zone dépend de la façon dont les données sont utilisées sur l'application.
Je ne l'ai pas utilisé dans la pratique, donc je serais heureux si vous pouviez partager quelque chose comme "Je fais ça chez moi!"!
Rails Guide What is Optimistic Locking
Recommended Posts