2015-02-19 3 views
1

Я проверяю эту линию контроллера:a == b возвращает true, a.attribute == b.attribute возвращает false; рубин

@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 

Я не понимаю, почему оператор сравнения говорит, что правопреемники [: канал] == канал, но их «активный» атрибут отличается.

+0

Кажется, что это работает, если вы вызываете 'channel.reload' (последнее выражение). Это означает, что 'channel' и' @ channel' являются разными объектами. Обновление не автоматически обновляет другое, хотя они могут ссылаться на одну и ту же запись в вашей базе данных. – Stefan

ответ

2

Я полагаю, канал является объектом ActiveRecord, и это так же, как делают:

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

channel1 == channel2 Так потому, что их личность такая же. (они оба канала и имеют одинаковый идентификатор)

Но если вы обновите один из них, другой будет устаревшим.

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

+0

Большое спасибо! –

+0

Я добавил ссылку на документы, которые были отправлены мне Yi Wen –

2

Поскольку равенство для моделей ActiveRecord основывается на их ID, а не каждый атрибут. Так что это та же модель, у них просто разные настройки для их «активного» атрибута. Вот почему он работает после перезагрузки.

Я думаю, что это могло бы работать, как вы ожидаете, если вы измените первую строку: @channel.update(active: true)

+0

Спасибо большое! –

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 решить, считает он, что оно равно b.bar, и нет ничего, что могло бы привести к тому, что они должны согласиться.

В вашем случае, похоже, проблема с консистенцией кеширования. Кажется, у вас есть два разных объекта, которые представляют одну и ту же запись базы данных, и одна из них имеет устаревшие данные.

+0

Это хороший момент. Благодаря! –

Смежные вопросы