Зачем использовать метод "перезагрузки" после сохранения объекта? (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
то же самое? Я взял метод перезагрузки, чтобы попробовать, и он не изменил ничего с тестом.
Что мне здесь не хватает?
Ответы
Ответ 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.