Je travaille sur les exercices du chapitre 6 du didacticiel de Hartl sur Rails 4. Le premier exercice vérifie que les adresses électroniques des utilisateurs sont correctement mémorisées:
require 'spec_helper'
describe User do
.
.
.
describe "email address with mixed case" do
let(:mixed_case_email) { "[email protected]" }
it "should be saved as all lower-case" do
@user.email = mixed_case_email
@user.save
expect(@user.reload.email).to eq mixed_case_email.downcase
end
end
.
.
.
end
Ce que je ne comprends pas, c'est pourquoi la méthode de «rechargement» est nécessaire ici. Une fois que @user.email
est défini sur le contenu de mixed_case_email
et saved , @user.reload.email
et @user.email
ne sont-ils pas la même chose? J'ai pris la méthode de rechargement juste pour l'essayer et cela ne semblait rien changer au test.
Qu'est-ce que j'oublie ici?
Oui, dans ce cas, @user.reload.email
et @user.email
est la même chose. Mais c'est une bonne pratique d'utiliser @user.reload.email
au lieu de @user.email
pour vérifier ce qui est exactement sauvegardé dans la base de données. Vous ne savez pas si vous ou quelqu'un ajoutez du code dans after_save qui change sa valeur, cela n'aura aucun effet sur vos tests.
EDIT: Et ce que vous vérifiez est également ce qui est enregistré dans la base de données afin que @user.reload.email
reflète exactement ce qui est enregistré dans la base de données, puis @user.email
Il est important de comprendre la différence entre la mémoire en mémoire et la base de données. Tout code Ruby que vous écrivez est en mémoire. Par exemple, chaque fois qu'une requête est exécutée, elle crée un nouvel objet en mémoire avec les données correspondantes de la base de données.
# @student is a in-memory object representing the first row in the Students table.
@student = Student.first
Voici votre exemple avec commentaires pour explication
it "should be saved as all lower-case" do
# @user is an in-memory Ruby object. You set it's email to "[email protected]"
@user.email = mixed_case_email
# You persist that objects attributes to the database.
# The database stores the email as downcase probably due to a database constraint or active record callback.
@user.save
# While the database has the downcased email, your in-memory object has not been refreshed with the corresponding values in the database.
# In other words, the in-memory object @user still has the email "[email protected]".
# use reload to refresh @user with the values from the database.
expect(@user.reload.email).to eq mixed_case_email.downcase
end
Pour voir une explication plus complète voir ce post .
reload
Recharge les attributs de l'objet (ici @user) depuis la base de données. Cela garantit toujours que l'objet possède les dernières données actuellement stockées dans la base de données.
Avec cela, nous pouvons aussi éviter
ActiveRecord::StaleObjectError
Cela se produit normalement lorsque nous essayons de changer l'ancienne version de l'objet.
Ce devrait être la même chose. Le problème est que la méthode reload recharge l'objet à partir de la base de données. Vous pouvez maintenant vérifier si votre objet de test nouvellement créé est réellement enregistré avec les attributs corrects/attendus.
Ce que l'exemple veut vérifier, c'est si le rappel before_save
dans app/models/user.rb
fait son travail. Le rappel before_save
doit définir le courrier électronique de chaque utilisateur sur la valeur minimale avant son enregistrement dans la base de données. Le chapitre 6 de l'exercice 1 souhaite ainsi vérifier si sa valeur dans la base de données, qui peut être extraite à l'aide de la méthode reload
, est effectivement enregistrée en tant que valeur minimale.