Подтвердить что ты не робот

Проверка байпасных рельсов при создании объектов 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 для сборки данных образца или сохранения тестовых данных, В качестве альтернативы я мог удалить проверки; но тогда у меня не было бы валидаций.

Любые другие варианты?

4b9b3361

Ответ 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?