Обход проверок Rails при создании объектов FactoryGirl - PullRequest
25 голосов
/ 04 октября 2011

У меня есть две модели (ModelA и ModelB) и фабрики FactoryGirl для каждой. Я хочу, чтобы фабрика ModelB могла (A) создавать тестовые данные и (B) создавать (без сохранения в базе данных) образцы данных для отображения клиентам. У меня проблемы с получением (A) работы из-за проверок Rails в моих моделях.

Modela:

class ModelA < ActiveRecord::Base
  belongs_to :model_b
  validates_presence_of :model_b
end

Фабрика для 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

Фабрика для 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 пытается сохранить фабричный объект перед сохранением его ассоциаций. Я понимаю, что мог бы заставить фабрику для ModelB создать связанную с ней ModelA (а не построить ее) - однако тогда я потерял бы гибкость возможности использовать фабрику ModelA либо для построения выборочных данных, либо для сохранения тестовых данных. С другой стороны, я мог бы удалить проверки; но тогда у меня не было бы проверок.

Есть ли другие варианты?

Ответы [ 4 ]

26 голосов
/ 22 декабря 2013

Как насчет этого?

FactoryGirl.build(:model_a).save(validate: false)

РЕДАКТИРОВАТЬ: Как Скотт Макмиллин комментирует ниже, если вы хотите, чтобы встроенный объект был переменной, вы можете сделать это:

model_a = FactoryGirl.build(:model_a)
model_a.save(validate: false)
17 голосов
/ 05 октября 2011

Я искал пару решений.

Одним из них является создание собственного прокси, показанного здесь: http://codetunes.com/2009/11/05/fixtures-without-validation-with-factory-girl

Другой способ - установить на заводе блок to_create:

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 голосов
/ 05 октября 2011

Эта круговая проверка не очень хорошая идея.Как вы собираетесь строить реальные объекты в базе данных?Имхо, это просто невозможно.

Сначала необходимо сохранить объекты в базе данных, идентификатор назначается базой данных, и только после создания / сохранения объекта вы можете ссылаться на объект с помощью идентификатора во внешнем ключе.Таким образом, чтобы иметь возможность ссылаться на запись в базе данных, ее необходимо сначала сохранить.Но если проверки требуют, чтобы идентификаторы были известны и представлены перед сохранением ...

В отношении belongs_to внешний ключ находится в таблице, и тогда вы можете указать, что ключ должен бытьподарок.С отношением has_one внешний ключ находится в другой таблице, и вы не можете выразить проверку того, что элемент должен присутствовать.Поэтому вы должны удалить проверку из ModelB.

Надеюсь, это поможет.

[ОБНОВЛЕНИЕ]

Вы пытались написать:

FactoryGirl.define do
  factory :model_a do
    some_attr "hello"
    model_b
  end
end
1 голос
/ 16 мая 2016

Я также столкнулся с той же проблемой, что модель не удается сохранить, когда не удалось сохранить сопоставления.

Возможно, попробуйте это: https://github.com/thoughtbot/factory_girl/issues/369?

...