71 votes

Comment puis-je savoir quand il faut "rafraîchir" mon objet modèle dans Rails ?

Voici une partie d'un test d'intégration que j'effectue :

user = User.first
assert !user.is_active?

get confirm_email_user_url(user),:confirmId => user.mail_confirmation_hash

assert_equal response.status,200
# because confirm_email_user_url modifies the activation state of the object
user = User.first
assert_equal user.state,"activated"

J'ai passé la dernière heure à déboguer ceci :). Dans ma version initiale, je ne réinitialisais pas user après l'accès à confirm_email_user_url, et l'état était toujours inactive même si l'utilisateur a été activé.

Comment puis-je savoir si je dois "recharger" (faute d'un meilleur nom) mon objet modèle ? Que dois-je appeler pour le faire ?

3 votes

En effet, reload est le terme approprié et vous pouvez utiliser user.reload

1 votes

138voto

dantswain Points 2895

Vous devez appeler user.reload chaque fois que les données ont changé dans la base de données.

Dans le code ci-dessus, l'objet "user" est créé en mémoire à partir des données extraites de la base de données par l'utilisateur. User.first . Alors, il semble que votre confirm_email_user_url modifie le base de données . L'objet n'est pas au courant de cela jusqu'à ce que vous reload il, qui ré-acquiert les données de la base de données.

Je ne suis pas sûr qu'il existe un moyen programmatique de savoir quand vous devrez recharger l'objet, mais en tant que développeur, vous devez être conscient de ce qui se passe et le gérer de manière appropriée. Dans la plupart de mes expériences (qui sont quelque peu limitées), ce n'est un problème que pendant les tests. En production, il n'est pas courant qu'un objet soit modifié dans la base de données alors qu'il est chargé en mémoire. Ce qui se passe généralement, c'est que l'objet en mémoire est modifié et ensuite sauvegardé dans la base de données (c'est-à-dire, user.email = "foo@bar.com" suivi par user.save ). Je suppose que si vous aviez une application à forte activité où de nombreux utilisateurs pourraient modifier quelque chose en peu de temps, vous voudriez être prudent à ce sujet.

0 votes

Je ne comprends pas, user = User.first ne le fait pas. User.first déclenchera à nouveau la requête ? elle devrait se recharger automatiquement ? non ?

0 votes

User.first va interroger à nouveau la base de données. Vous pouvez le vérifier en ouvrant rails c dans une fenêtre et tail -f log/development.rb dans l'autre. Ensuite, dans la console, tapez user = User.first deux fois. Vous verrez deux requêtes dans la seconde fenêtre avec les logs

6voto

Thomas Fankhauser Points 1899

En fait, cela ne fonctionne pas vraiment lorsque vous faites des choses sur le modèle lui-même, par exemple Report.count . Après avoir essayé à l'infini de réinitialiser les informations de la colonne ou de récupérer une instance du premier/dernier enregistrement et de la recharger, la seule chose qui m'a aidé a été de reconnecter la base de données entre les comptages comme ceci :

initial_count = Report.count

# do something, like invoking a rake task that imports the reports, ..

Report.connection.reconnect!
final_count = Report.count

Cela fonctionne pour Rails 2.3.8+, je ne sais pas pour les versions 3+.

0 votes

Pour mon cas d'utilisation particulier (plusieurs requêtes accédant aux mêmes données, puis une requête mettant à jour les données, et la deuxième requête essayant d'obtenir la mise à jour), l'équivalent de user.reload n'a pas fonctionné, mais Report.connection.reconnect ! a fonctionné.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X