web-dev-qa-db-fra.com

Comment savoir quand «actualiser» mon objet modèle dans Rails?

Voici une partie d'un test d'intégration que je fais:

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 avoir accédé à confirm_email_user_url, et l'état était toujours inactive même si l'utilisateur était activé.

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

60
Geo

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

Dans votre code ci-dessus, l'objet "utilisateur" est créé en mémoire à partir des données extraites de la base de données par User.first. Ensuite, il ressemble à votre confirm_email_user_url modifie la base de données . L'objet ne sait rien à ce sujet jusqu'à ce que vous reload, qui ré-acquiert les données de la base de données.

Je ne sais pas s'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 gérer de manière appropriée. Dans la plupart de mon expérience (qui est quelque peu limitée), ce n'est qu'un problème lors des 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 produit généralement, c'est que l'objet en mémoire est modifié puis enregistré dans la base de données (c'est-à-dire user.email = "[email protected]" suivi par user.save). Je suppose que si vous aviez une application très active où de nombreux utilisateurs pourraient modifier quelque chose en peu de temps, vous voudriez faire attention à ce sujet.

127
dantswain

Btw. cela ne fonctionne pas vraiment quand vous faites des choses sur le modèle lui-même comme Report.count. Après des tentatives sans fin de réinitialiser les informations de la colonne ou d'obtenir une instance du premier/dernier enregistrement et de la recharger, la seule chose qui m'a aidé était de reconnecter la base de données entre les décomptes 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 a fonctionné pour Rails 2.3.8+, je ne connais pas les versions 3+.

6
Thomas Fankhauser