ruby-on-rails 为什么在保存对象后使用'reload'方法?(Hartl Rails Tut 6.30)

pcrecxhr  于 5个月前  发布在  Ruby
关注(0)|答案(5)|浏览(61)

我正在做Hartl's Rails 4的第6章的练习。第一个练习测试确保用户电子邮件地址正确地大小写:

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

字符串
我不明白的是为什么这里需要reload方法。一旦@user.email被设置为mixed_case_email的内容并保存@user.reload.email@user.email不是一回事吗?我把reload方法拿出来只是为了尝试一下,它似乎没有改变任何东西。
我错过了什么?

ltskdhd1

ltskdhd11#

是的,在这种情况下,@user.reload.email@user.email是一样的。但是使用@user.reload.email而不是@user.email来更准确地检查数据库中保存的内容是一个很好的做法。我的意思是,你不知道如果你或别人在after_save中添加了一些代码,改变了它的值,那么它不会对你的测试产生影响。

**编辑:**而且您正在检查的是数据库中保存的内容,因此@user.reload.email@user.email更准确地反映了数据库中保存的内容

kfgdxczn

kfgdxczn2#

内存vs数据库

理解内存和数据库的区别很重要。你写的任何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 "[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

pbwdgjma

pbwdgjma3#

reload

字符串
从数据库中删除对象(这里是@user)的属性。它始终确保对象具有当前存储在数据库中的最新数据。
这样我们也可以避免

ActiveRecord::StaleObjectError


这通常发生在我们尝试更改对象的旧版本时。

wlwcrazw

wlwcrazw4#

应该是一样的。关键是reload方法从数据库中重新加载对象。现在你可以检查你新创建的测试对象是否真的保存了正确的/预期的属性。

f5emj3cl

f5emj3cl5#

这个例子要检查的是app/models/user.rb中的before_save回调是否完成了它的工作。before_save回调应该在将每个用户的电子邮件保存到数据库之前将其设置为小写,因此第6章练习1要测试它在数据库中的值(可以使用方法reload检索)是否有效地保存为小写。

相关问题