Подтвердить что ты не робот

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

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

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

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

Что мне здесь не хватает?

4b9b3361

Ответ 1

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

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

Ответ 2

Внутренняя память и база данных

Важно понимать разницу между встроенной памятью и базой данных. Любой код 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 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

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

Ответ 3

reload 

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

При этом мы также можем избежать

ActiveRecord::StaleObjectError

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

Ответ 4

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

Ответ 5

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