web-dev-qa-db-fra.com

Pourquoi utiliser la méthode 'reload' après avoir sauvegardé l'objet? (Hartl Rails Tut 6.30)

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?

28
sixty4bit

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

32
Hardik

En mémoire vs base de données

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

Votre exemple

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 .

20
Derrick Mar
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.

7

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.

4
rails4guides.com

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.

0
Asarluhi