2015-12-15 4 views
1

У меня есть следующие настройки фабрикиFactoryGirl и ассоциации проверки

FactoryGirl.define do 
    factory :image do 
    title 'Test Title' 
    description 'Test Description' 
    photo File.new("#{Rails.root}/spec/fixtures/louvre_under_2mb.jpg") 
    after(:build) do 
     FactoryGirl.build_list(:category, 1) 
    end 
    end 
end 

В рамках моей модели у меня есть эти валидаций

class Image < ActiveRecord::Base 
    has_many :categories 
    validates :title, presence: { message: "Don't forget to add a title" } 
    validates :description, presence: { message: "Don't forget to add a description" } 
    validates :categories, presence: { message: 'Choose At Least 1 Category' } 
end 

Когда я запускаю этот тест он не

RSpec.describe Image, type: :model do 
    it 'should have a valid Factory' do 
    expect(FactoryGirl.build(:image)).to be_valid 
    end 
end 

Failure/Error: expect(FactoryGirl.build(:image)).to be_valid 
expected #<Image id: nil, title: "Test Title", description: "Test Description", photo_file_name: "louvre_under_2mb.jpg", photo_content_type: "image/jpeg", photo_file_size: 65618, photo_updated_at: "2015-12-15 08:01:07", created_at: nil, updated_at: nil> to be valid, but got errors: Categories Choose At Least 1 Category 

Am I приближаясь к этому неправильно, поскольку я думал, что валидации не ударят, пока весь объект не будет cr eated? или я думаю об этом неправильно?

Благодаря

+0

'FactoryGirl.build_list (: категория, 1)' строит массив с одной категорией, но ни один массив, ни категория связана с изображением , – Stefan

ответ

2

проблема в этой части.

after(:build) do 
    FactoryGirl.build_list(:category, 1) 
end 

это создаст список категорий размером 1, но эти категории не связаны с объектом изображения. Правильный способ заключается в следующем:

transient do 
    categories_count 1 
end 
after(:build) do |image, evaluator| 
    image.categories = build_list(:category, evaluator.categories_count) 
end 

или

transient do 
    categories_count 1 
end 
categories { build_list(:category, categories_count) } 

лично я выбрал бы этот последний вариант.

атрибут photo также является проблематичным. FactoryGirl - все о гибкости создания записей. Но способ, которым вы его используете, не будет представлять никакой гибкости, поэтому атрибут фото будет разделяться между всеми записями, которые вы создадите с использованием этой фабрики. И рано или поздно вы столкнетесь с некоторыми головными болями.

Таким образом, правильный способ создания атрибута photo заключается в следующем.

transient do 
    photo_name 'default_photo.jpg' 
end 
photo { File.new(File.join(Rail.root, "spec/fixtures", photo_name) } 

, чем вы можете использовать его таким образом

FactoryGirl.build(:image, photo_name: 'new_photo_name.jpg') 
+0

спасибо за ваш ответ, если я хотел создать список категорий с категориями «0», так что я мог бы сбой в построении объекта, могу ли я просто установить «categories_count» на 0? – Richlewis

+0

Спасибо за подсказку по использованию 'transient', реальной полезной ... мысли о создании category_count в 0? – Richlewis

+0

да, вы можете просто сделать это, 'FactoryGirl.build (: image, categories_count: 0)' это создаст образ без связанных категорий. –

0

Я бы рекомендовал не использовать after метод в изображении фабрики. Вы должны создать правильную связь. Используя это, вы устраните ошибку проверки, и в будущем у вас будут другие проблемы.

class Image 
    accepts_nested_attributes_for :categories 
end 

FactoryGirl.define do 
    factory :image do 
    categories_attributes { [FactoryGirl.attributes_for(:category)] } 
    end 
end 
+0

Спасибо за ваши комментарии, не могли бы вы привести пример, пожалуйста? Я просто не хочу жестко указывать идентификатор здесь? и 'photo' не является ассоциированным объектом – Richlewis

+0

Вы имеете в виду это' category {[FactoryGirl.build (: category)]} ' – Richlewis

+0

Я отредактировал свой ответ. –