a == b返回true,a.attribute == b.attribute返回false;红宝石

时间:2015-02-19 16:55:11

标签: ruby ruby-on-rails-3

我正在测试控制器的这一行:

@channel.update_attribute(:active, true)

expect(channel.active).to be_true fails (my variable is named 'channel')
expect(assigns[:channel].active).to be_true passes

assigns[:channel] == channel
=> true

assigns[:channel].active == channel.active
=> false

assigns[:channel].active == channel.reload.active
=> true

我不明白为什么比较运算符会指定[:channel] == channel,但他们的“active”属性不同。

3 个答案:

答案 0 :(得分:2)

我认为一个频道是一个ActiveRecord对象,它和做的一样:

channel1 = Channel.find(1)
channel2 = Channel.find(1)

所以channel1 == channel2因为他们的身份是一样的。 (它们都是频道,并具有相同的ID)

但是如果你更新其中一个,那么另一个将是陈旧的。

channel1.active = "different value"
channel1.save
channel1.active != channel2.active

执行channel2.reload将从数据库中获取属性,现在

channel1.active == channel2.active

http://api.rubyonrails.org/classes/ActiveRecord/Core.html#method-i-3D-3D

答案 1 :(得分:2)

因为ActiveRecord模型的相等性是基于它们的ID而不是每个属性。所以它是相同的模型,他们只是为他们的"活跃"设置了不同的设置。属性。这就是为什么它重新加载后才有效。

我认为如果你改变第一行,它可能会像你期望的那样: @channel.update(active: true)

答案 2 :(得分:0)

我不确定在您的具体情况下发生了什么确切,但总体情况并不奇怪:

class Foo
  attr_reader :bar

  def initialize
    @bar = Bar.new
  end

  def ==(*) true end

  class Bar
    def ==(*) false end
  end
end

a = Foo.new
b = Foo.new

a == b
# => true

a.bar == b.bar
# => false

这只是面向对象封装的结果。最多a决定它是否认为它等于b,并且最多a.bar来决定它是否认为它等于{{1}并且没有什么可以强制要求两者达成一致。

在您的情况下,似乎存在一些缓存一致性问题。您似乎有两个不同的对象,它们都代表相同的数据库记录,其中一个对象具有陈旧数据。