我正在为Hartl的Rails 4教程第6章练习。第一个练习测试以确保正确地缩小用户电子邮件地址:
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
不是同一回事吗?我把重装方法拿出去尝试它并且似乎没有改变测试的任何东西。
我在这里缺少什么?
答案 0 :(得分:32)
是的,在这种情况下@user.reload.email
和@user.email
是一回事。但是最好使用@user.reload.email
而不是@user.email
来检查数据库中确切保存的内容我的意思是你不知道你或者是否有人在after_save中添加一些代码来改变它的值然后它会对你的考试没有影响。
修改强>
此外,您正在检查的是数据库中保存的内容,因此@user.reload.email
完全反映了数据库中保存的内容,然后@user.email
答案 1 :(得分:21)
了解内存和数据库的区别非常重要。您编写的任何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
要查看更详尽的说明,请参阅此post。
答案 2 :(得分:7)
reload
从数据库重新加载对象(此处为@user)的属性。它始终确保对象具有当前存储在数据库中的最新数据。
有了这个,我们也可以避免
ActiveRecord::StaleObjectError
这通常在我们尝试更改旧版本的对象时出现。
答案 3 :(得分:4)
它应该是一回事。重点是reload方法从数据库重新加载对象。现在,您可以检查新创建的测试对象是否实际保存了正确/预期的属性。
答案 4 :(得分:0)
示例要检查的是before_save
中的app/models/user.rb
回调是否完成了它的工作。 before_save
回调应该在将每个用户的电子邮件保存到数据库之前将其设置为小写,因此第6章练习1想要测试它在数据库中的值是否可以使用方法reload
检索,被有效地保存为小写。