Проверка байпасных рельсов при создании объектов FactoryGirl
У меня есть две модели (ModelA и ModelB) и фабрики FactoryGirl для каждого. Я хочу, чтобы factory для ModelB мог (A) создавать тестовые данные и (B) создавать (без сохранения в базу данных) образцы данных для отображения клиентам. У меня возникли проблемы с получением (A) работы из-за проверки Rails в моих моделях.
Modela:
class ModelA < ActiveRecord::Base
belongs_to :model_b
validates_presence_of :model_b
end
Factory для ModelA:
FactoryGirl.define do
factory :model_a do
some_attr "hello"
model_b { FactoryGirl.build :model_b }
end
end
ModelB
class ModelB < ActiveRecord::Base
has_one :model_a
end
Factory для ModelB
FactoryGirl.define do
factory :model_b do
some_attr "goodbye"
end
end
Я не могу создавать объекты с этих фабрик без ошибок проверки:
ruby> FactoryGirl.create :model_a
ActiveRecord::RecordInvalid: Validation failed: ModelB can't be blank
Похоже, что FactoryGirl пытается сохранить объект factory перед сохранением его связей. Я понимаю, что я мог бы иметь factory для ModelB создать связанный с ним ModelA (а не создавать его), однако я бы потерял гибкость в возможности использовать ModelA factory для сборки данных образца или сохранения тестовых данных, В качестве альтернативы я мог удалить проверки; но тогда у меня не было бы валидаций.
Любые другие варианты?
Ответы
Ответ 1
Я рассмотрел пару решений.
Один из них - создать пользовательский прокси, который показан здесь:
http://codetunes.com/2009/11/05/fixtures-without-validation-with-factory-girl
Другой - установить блок to_create
в factory:
FactoryGirl.define do
factory :model_a do
model_b { FactoryGirl.build :model_b }
to_create do |instance|
instance.model_b.save!
instance.save!
end
end
end
Ответ 2
Как насчет этого?
FactoryGirl.build(:model_a).save(validate: false)
EDIT: Как Скотт Макмиллин ниже, если вы хотите, чтобы встроенный объект был переменной, вы можете это сделать:
model_a = FactoryGirl.build(:model_a)
model_a.save(validate: false)
Ответ 3
Эта круговая проверка не является хорошей идеей. Как вы собираетесь создавать реальные объекты в базе данных? Имхо это просто невозможно.
Сначала вам нужно сохранить объекты в базе данных, идентификатор присваивается базой данных, и только после создания/сохранения объекта вы можете ссылаться на объект, используя идентификатор во внешнем ключе. Поэтому, чтобы иметь возможность ссылаться на запись в базе данных, ее необходимо сохранить в первую очередь. Но если проверки требуют, чтобы идентификатор был известен и присутствовал до сохранения...
В отношении belongs_to
внешний ключ находится в таблице, а затем вы можете выразить необходимость присутствия ключа. С отношением has_one
внешний ключ находится в другой таблице, и вы не можете выразить подтверждение того, что элемент должен присутствовать. Поэтому вы должны удалить проверку с ModelB
.
Надеюсь, что это поможет.
[ОБНОВЛЕНИЕ]
Вы пытались написать:
FactoryGirl.define do
factory :model_a do
some_attr "hello"
model_b
end
end
Ответ 4
Я столкнулся с той же проблемой, что модель не может сэкономить, когда ассоциации не удалось сохранить.
Возможно, попробуйте следующее: https://github.com/thoughtbot/factory_girl/issues/369?