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

Ошибка FactoryGirl, has_one и проверка

Это две простые модели:

class Post < ActiveRecord::Base
  has_one :asset, :dependent => :destroy

  validates :asset, presence: true
end

class Asset < ActiveRecord::Base
  belongs_to :post
end

Я пытаюсь создать factory следующим образом:

  factory :post do
    # fields...

    asset { FactoryGirl.create(:asset) }
  end

  factory :asset do
    # fields...

    post
  end

Но, запустив spec, он входит в цикл.

Я также попытался это сделать:

  factory :post do
    # fields...

    before(:create) do |post, evaluator|
      FactoryGirl.create_list(:asset, 1, post: post)
    end
  end

Но закончилось "Ошибка проверки: Asset не может быть пустым".

Как я могу представить свою ситуацию?

4b9b3361

Ответ 1

Я решил эту проблему, используя обратный вызов после (: build).

factory :post do
    # fields...
    after(:build) do |post|
      post.asset ||= FactoryGirl.build(:asset, :post => post)
    end
end

factory :asset do
    # fields...
    after(:build) do |asset|
      asset.post ||= FactoryGirl.build(:post, :asset => asset)
    end
end

Таким образом, связанные объекты будут созданы до того, как будет сохранен класс владельца, поэтому проверка прошла.

Ответ 2

Проверка не выполняется, поскольку, когда FactoryGirl создает Post, должен присутствовать актив. Поэтому в ваших определениях FactoryGirl вы можете создать Asset как часть создания Post. Вставьте что-то вроде файла FactoryGirl post.rb:

asset { FactoryGirl.create(:asset) }

или

Вы можете создать Asset как часть вашего объявления Post в вашем спецификационном файле, например следующее:

asset = FactoryGirl.create(:asset)

FactoryGirl.create(:post, :asset => asset)

Спасибо.

Ответ 3

Вы можете предварительно загрузить дочернюю ассоциацию, передав ее следующим образом:

FactoryGirl.define do
  factory :post do
    asset { Asset.create! }
  end
end

(Лучше, используя Asset factory, чтобы сгенерировать его связанный актив с предварительно заданными настройками).

Другим ручным способом было бы создать Asset через FactoryGirl.create(: asset) и передать его в создание переменной, то есть:

asset = FactoryGirl.create(:asset)
post = FactoryGirl.create(:post, asset: asset)

Ответ 4

ошибка Validation failed: Asset can't be blank заключается в том, что похоже, что у вас есть связь назад на ваших фабриках.

factory :post do
  # fields...
end

Поэтому, когда вы создаете post, нет asset, поэтому проверка не выполняется. Попробуйте это

factory :post do
# fields...
  asset
end

Посмотрите на эту страницу wiki и раздел ассоциаций. Он также объясняет разницу между create и build с ассоциациями