2016-12-06 13 views
0

Я обновляемый мое приложение от Rails 4.0 до 4.1 (на моем пути к 4.2) и есть тесты, как это, что не удается:перегрузочный объект ActiveRecord в RSpec обновляет запись в базе данных вместо перезагрузки объекта из БДА

describe "#restore_disabled_account" do 
    let(:username) { 'username' } 
    let(:email) { '[email protected]' } 
    let(:m3_user) { create(:user, username: username, 
            email: email, 
           archived: false, 
        propagate_in_test_mode: true) } 
    let(:m2_user) { Maestro2::User.where(UserID: m3_user.id).first } 

    before do 
    m3_user.disable_account 
    end 

    it "unarchives the account" do 
    m3_user.restore_disabled_account 
    m3_user.reload 
    expect(m3_user.archived).to be_falsey 
    end 
end 

Я проверил, что база данных содержит запись с ожидаемыми атрибутами в начале этого теста. Когда вы отлаживаете тест и останавливаетесь перед операцией reload, я вижу, что запись db была обновлена, как ожидалось (в архиве указано false, а другие атрибуты обновляются, как ожидалось). Я также вижу, что объект m3_user обновлен с теми же атрибутами. Когда я делаю шаг вперед, чтобы запустить шаг перезагрузки и запросить db, я вижу, что запись вернулась в исходное состояние, как и объект в памяти. Затем тест завершился неудачно, потому что m3_user.archived является истинным.

Может ли кто-нибудь сказать мне, почему? Все тесты в моем пакете проходили перед началом обновления. Приложение в настоящее время использует рубин 2.2.4, Rails 4.1.16, RSpec 3.5.3 и RSpec-рельсы 3.5.2

Для справки, два пользователя вызовов метода класса ниже:

def disable_account 
    self.update_attributes(username: "disabled_#{id}_#{username}", 
          email: "disabled_#{id}_#{email}", 
         archived: true) 
end 

def restore_disabled_account 
    self.update_attributes(username: username.gsub(/^disabled_#{id}_/, ''), 
          email: email.gsub(/^disabled_#{id}_/, ''), 
         archived: false) 
end 
+0

Это не связано с вопросом, но '' # {username} "' избыточно. Все, что вы интерполируете, это сама переменная, поэтому просто нужно «имя пользователя: имя пользователя» и т. Д. Интерполяция - это когда строка содержит больше, чем просто динамический код Ruby. – sixty4bit

+0

также можете добавить содержимое метода '# restore_disabled_account' и попытаться удалить баг'! 'Из' let! '? – sixty4bit

+0

Я добавил код, который вы просили. Удаление ударов не изменило результаты, к сожалению. – Warren

ответ

0

короткий ответ: Оказывается, ActiveRecord 4.1 изменил метод reload, чтобы вызвать новый закрытый метод под названием reset_changes. У моего класса User также был метод reset_changes, поэтому мой метод переопределил то, что должно было быть вызвано.

Длинный ответ: чем больше я смотрел на это, тем больше я подозревал что-то уникальное для моей модели User. Другие тесты с использованием reload выполнялись так, как ожидалось. Затем я наткнулся на метод reset_changes в User. Посмотрев, что он сделал (обновляя запись db с предыдущими значениями), я отбросил в нее инструкцию puts, чтобы увидеть, вызвана ли она. Как только это было подтверждено, я сбросил обратную линию звонящего, которая указала мне на https://github.com/rails/rails/blob/4-1-stable/activerecord/lib/active_record/attribute_methods/dirty.rb#L37

Я изменил свой метод модели пользователя на undo_changes, и мои спецификации зеленые.

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

  • Нет связанных вопросов^_^