2016-09-13 1 views
6

Je pense que j'ai tout éliminé, mais je ne suis pas sûr de comprendre assez bien l'OL pour être sûr. En général, disons que vous et moi sommes en équipe pour garder un foo à jour. Je suis dans une pièce et décide de gagner du temps. Je mettrai moi-même à jour le truc. Donc, je commence à le mettre à jour. Une minute plus tard, vous avez la même idée et vous vous connectez à la page d'édition pour la mettre à jour également. Que se passe-t-il si je finis premier? Que se passe-t-il si vous finissez premier? Dans une configuration où il échoue, comment distingue-t-on quelqu'un qui édite et quelqu'un qui lit? Si je catch et recharger pour mettre à jour le verrou, je perds tous mes changements, comment est-ce résolu? Ici, il est facile de refaire la mise à jour, mais cela fait potentiellement partie d'un objet de formulaire plus compliqué. Mon problème spécifique est venu quand (mieux je peux faire) chargé une copie dans mon navigateur, plus tard oublié à ce sujet et puis un dans ma console (également lock: 0?) Ne pouvait pas mettre à jour celui de ma console avec erreur d'objet périmé. Remarqué la chose du navigateur. Fermé ma console. J'ai essayé de recharger mon navigateur et j'ai aussi eu une erreur d'objet périmé. Voici le code qui est défaillant:Obtention d'une erreur d'objet Stale. Verrouillage optimiste: comment ça marche?

=> 7:  self.update_attributes({ 
    8:   failed_view_attempts: self.failed_view_attempts += 1, 
    9:   failed_view_at: Time.now 
    10:  }) 
    11:  end 
(byebug) self 
#<Product id: 12... lock_version: 0> 

#=> ActiveRecord::StaleObjectError (Attempted to update a stale object: Product.) 

choses que j'ai essayé:

Pour voir si une autre instance était chargée, j'ai ajouté puts "CALLED !!!!" dans un rappel after_initialize, mais il ne sera imprimé une fois.

Et vérifier self.changed après avoir sauvé de l'erreur et retourner ["updated_at", "failed_view_attempts", "failed_view_at"]

Répondre

1

Nécessité de définir lock_version colonne par défaut à zéro (0).

0

verrouillage Optimiste est basé sur un numéro de version d'objet.

lecture et de l'objet ne devraient pas affecter le numéro de version du tout.

Si vous essayez de mettre à jour un objet, ce numéro de version est comparé (en fait la mise à jour sql instruction est utilisée par exemple « mise à jour ... où version = 1 et ... ») et une augmentation de la mise à jour.

Si la comparaison échoue lorsque vous essayez de mettre à jour, vous obtenez l'erreur d'objet vicié. Cela signifie que l'objet a été modifié par quelqu'un d'autre pendant que vous étiez en train de faire vos changements.

Pour résoudre cette erreur, vous devez charger à nouveau l'objet pour obtenir la version réelle et peut-être fusionner les changements manuellement (présenter à l'utilisateur quelques informations à ce sujet, et laisser l'utilisateur décider par exemple).

+0

Mais, si pendant que je suis quelqu'un appelle l'édition d'une instance de la même ligne de le lire il percuter le numéro de version. C'est basé sur le chargement, pas sur ce que vous faites avec, n'est-ce pas? – MCB

+0

pas vraiment, si vous le chargez, le numéro de version reste le même, sinon il y aura beaucoup de mises à jour donc le numéro de version est mis à jour (ie: update version = 2 où version = 1) et si aucun enregistrement ne correspond l'où vous obtenez alors l'erreur d'objet périmé. Le problème avec le rechargement de page peut être qu'il est mis en cache et que vous ne rechargez pas l'objet à partir de DB. –

+0

Oui, le navigateur utilisant une version en cache est quelque chose que je connais déjà – MCB