Как исправить ошибку при сохранении ActiveRecord в spec?

Добрый день.

Сегодня появилась специфическая ошибка: есть spec тест с несколькими examples. Изначально для всех контекстов в блоке before :all я создаю общие данные для теста с помощью FactoryGirl.create().
В каждом тест кейсе в одном из этих объектов изменяются 2 поля c нужными мне параметрами и сохраняются при помощи save!

Однако, все отлично работает только для первого тест кейса, при последующих вызовах save! появляется ошибка:
Mysql2::Error: Duplicate entry '154' for key 'PRIMARY': INSERT INTO `table_name`

Т.е. по какой-то причине ActiveRecord считает эту запись новой, хотя она была уже создана еще до начала тестов. Вызов в дебаггере object.new_record? в блоке before :each еще до изменения данных возвращает true.
Но, если объект был создан при помощи Model_name.create!(), то вызов new_record? возвращает false.
Изучение гема active_record не дало ответа на мой вопрос.
Может, кто-нибудь сталкивался с этой проблемой и знает её решение?
RoR v. 3.2.18, rspec-rails v. 2.14.0, ruby v. 2.0.0-p451, factory_girl_rails v. 4.2.1
  • Вопрос задан
  • 2394 просмотра
Решения вопроса 1
@Nike0 Автор вопроса
Проблема оказалась куда более странной - в spec_helper.rb прописана следующая конструкция:
config.around(:each) do |example|
  DatabaseCleaner.cleaning do
    example.run
  end
end

Видимо, после роллбека одного it'a сбрасывалось состояние объекта, хранящееся в @new_record (переменная ActiveRecord) и он считался новым, что и вызывало ошибку.

UPD. Перед всеми it'ами в блоке before :all (который не входит в транзакцию), создается запись и сохраняется в БД. В каждом из тест кейсов мы эту запись обновляли и сохраняли. После завершения блока все сохранные данные откатывались, включая состояние объекта (новый или нет), хотя запись в БД осталась, из-за чего в будущем возникает ошибка с PRIMARY KEY.
Фикс оказался довольно простым - транзакции оставил включенными в spec_helper.rb, но теперь по-другому оперировал с объектом, без его непосредственного сохранения (мы изменили какие-то поля, они сохранились в памяти, но в следующих тест кейсах мы продолжаем работать с не измененной записью).
Также был протестировано обновление записи через update_column.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы