Зачем использовать метод 'reload' после сохранения объекта? (Hartl Rails Tut 6.30)

Я работаю над упражнениями для Главы 6 руководства по Rails 4 Хартла. Первое упражнение тесты, чтобы убедиться, что адреса электронной почты пользователя в нижнем регистре правильно:

require 'spec_helper'

describe User do
  .
  .
  .
  describe "email address with mixed case" do
    let(:mixed_case_email) { "Foo@ExAMPle.CoM" }

    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

чего я не понимаю, так это почему здесь необходим метод "перезагрузки". После @user.email имеет значение содержимое mixed_case_email и спас, не @user.reload.email и @user.email то же самое? Я взял метод перезагрузки, чтобы попробовать его, и, похоже, ничего не изменилось с тестом.

что я пропустила?

5 ответов


да, в данном случае @user.reload.email и @user.email это одно и то же. Но это хорошая практика, чтобы использовать @user.reload.email вместо @user.email чтобы проверить, что именно сохранено в базе данных, я имею в виду, что вы не знаете, добавляете ли вы или кто-то код в after_save, который изменяет его значение, тогда он не будет влиять на ваши тесты.

EDIT: А также то, что вы проверяете, это то, что сохранено в базе данных so @user.reload.email точно отражает то, что сохранено в базе данных, то @user.email


в памяти против базы данных

важно понимать разницу между памятью и базой данных. Любой код ruby, который вы пишете, находится в памяти. Например, при выполнении запроса создается новый объект в памяти с соответствующими данными из базы данных.

# @student is a in-memory object representing the first row in the Students table.
@student = Student.first

ваш пример

вот ваш пример с комментариями для объяснения

it "should be saved as all lower-case" do
    # @user is an in-memory ruby object. You set it's email to "Foo@ExAMPle.CoM"
    @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 "Foo@ExAMPle.CoM".
    # use reload to refresh @user with the values from the database.
    expect(@user.reload.email).to eq mixed_case_email.downcase
end

чтобы увидеть более подробное объяснение, см. Это в должности.


reload 

перезагружает атрибуты объекта (здесь @user) из базы данных. Он всегда гарантирует, что объект имеет последние данные, которые в настоящее время хранятся в базе данных.

С этим мы можем избежать

ActiveRecord::StaleObjectError

обычно это происходит, когда мы пытаемся изменить старую версию объекта.


Это должно быть то же самое. Все дело в том, что метод reload перезагружает объект из базы данных. Теперь вы можете проверить, действительно ли ваш вновь созданный тестовый объект сохранен с правильными/ожидаемыми атрибутами.


какой пример хочет проверить, является ли before_save обратный вызов в app/models/user.rb делает свою работу. The before_save обратный вызов должен установить каждый адрес электронной почты пользователя в downcase, прежде чем он будет сохранен в базе данных, таким образом, Глава 6 Упражнение 1 хочет проверить, если его значение в базе данных, которые могут быть получены с помощью метода reload, эффективно сохраняется как downcase.