Я догадываюсь, что происходит.Я думаю, что исправлением было бы изменить вашу проверку следующей строкой:
product.variants.reload.each do |v|
Я думаю, что случается, что когда вы вызываете variant1
в своем тесте, он запускает проверку для варианта1, которыйзвонит variants
на объекте продукта.Это запрашивает базу данных для связанных вариантов, и получает пустой результат.Однако, так как вариант 2 имеет тот же фактический объект продукта, этот объект продукта не будет повторно запрашивать базу данных и помнит (неправильно), что его варианты являются пустым результатом.
Еще одно изменение, которое может привести к выполнению теста:изменить свой тест следующим образом:
before do
@variant2 = FactoryBot.create(:variant, product_id: product.id, option_values: variant1.option_values)
end
Это тонкий, и я хотел бы знать, работает ли он.Это устанавливает поле product_id
для варианта 2, но не устанавливает объект product
, чтобы ассоциация была фактическим тем же объектом product
, который имеет вариант1.(На практике это более вероятно происходит в вашем реальном коде, потому что объект продукта не используется совместно с вариантами объектов.)
Еще одна вещь для вашего правильного решения (если все это правильно) - перезагрузитьно поместите весь свой код сохранения (и ваш код обновления) в транзакцию.Таким образом, не будет условия гонки двух вариантов, которые будут конфликтовать, потому что в транзакции первый должен завершить проверку и сохранить до того, как второй выполнит свою проверку, поэтому он обязательно обнаружит другой, который только что сохранил.
Некоторые предлагаемые методы отладки:
- Если возможно, просмотрите журнал, чтобы увидеть, когда выполняются запросы.Возможно, вы поймали, что вторая проверка не запрашивала варианты.
- Проверьте
object_id
.Возможно, вы поймали, что объекты продукта на самом деле были одним и тем же объектом. - Также проверьте
new_record?
, чтобы убедиться, что вариант1 сохранен перед проверкой варианта2.Я думаю, что это спасает, но было бы приятно узнать, что вы это проверили.