0

我在运行规范时遇到了一个奇怪的行为。

除非我取消注释行,否则此代码不起作用(baz.viewed未更新)baz.reload

describe "#..." do
  it "..." do
    baz = user.notifications.create!(title: "baz")
    baz.update_attribute(:created_at, Time.now + 3.day)

    # it sets `viewed` to `true` in the model to which `baz` is referred.
    user.dismiss_latest_notification!

    # baz.reload
    baz.viewed.should == true
  end
end

我不使用Sporkor运行规范Guard,但无论如何都不会重新加载此模型。

为什么会发生?或者,在规范中调用.reload方法是否正常?

4

1 回答 1

4

让我让这个案例更清楚一点:当行baz = user.notifications.create!(title: "baz")被执行时,会发生两件事:

1- 一个新的通知行被添加到数据库中。

2- 在内存中创建一个对象,代表这一行,并且可以用变量引用baz。请注意,baz它的查看值为 false(同时该行也是如此)。

现在我没有看到方法的实际实现

user.dismiss_latest_notification!

但是由于您没有将任何变量传递给它,我当然知道您有一个本着以下精神的代码:

def dismiss_latest_notification!
  latest_notification = self.notifications.last
  latest_notification.viewed = true
  latest_notification.save!
end

这里重要的一行是

   latest_notification = self.notifications.last

一个对象在内存中创建,代表相同的行baz,但存储在另一个变量 - latest_notification 中。

现在你有两个变量代表数据库中的同一行。当您在 latest_notification 上执行保存时,数据库会使用正确的查看值更新,但变量baz不会以任何方式更新以反映此更改。您别无选择,只能通过reload对其执行来强制使用最新值从数据库更新。

我认为摆脱重新加载的正确方法是稍微改变测试:

代替

baz.viewed.should == true

采用:

user.notifications.last.viewed.should be_true

在我看来,它更适合这个特定测试的目的。

于 2012-10-21T05:58:03.993 回答