2013-07-06 5 views
3

При попытке написать тесты rSpec, я немного смутился о том, как создавать записи FactoryGirl с ассоциациями.Factory Girl Traits

В принципе, у меня есть модель Quiz и модель Question. Они связаны через ассоциацию HABTM.

Вот мой Quiz завод:

FactoryGirl.define do 
    factory :quiz do 
    description 'Test' 

    # after(:create) { |quiz| quiz.create_sample_questions } 

    # trait :with_questions do 
    # after :create do |quiz| 
    #  5.times do |q| 
    #  quiz.questions << FactoryGirl.create(:question, :with_answers) 
    #  end 
    # end 
    # end 
    end 
end 

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

Ничего не работает, и моя черта, похоже, не вызывает вопросов.

Спасибо!

+0

Поздний отклик, но можете ли вы разместить свой завод 'question' вместе с тем, как вы вызываете' quiz' с признаком 'with_questions'? – vee

ответ

2

Мне было бы интересно увидеть другой ответ на этот вопрос, но я могу рассказать о своем личном опыте с использованием фабрик, ассоциаций и автоматической загрузки кучи объектов с обратными вызовами.

В принципе, я считаю, что «любитель», который я пытаюсь получить с чертами и обратными вызовами, тем больше проблем я причиняю будущим своим спецификациям. С такой витой логикой вы попадаете в беспорядки фабрик, где вы поцарапаете голову и задаетесь вопросом, что происходит.

Полностью гипотетический вопрос: что, если позже вам нужна викторина с вопросами? Ну, каждый quiz:with_questions имеет 5 вопросов. Вы тогда создаете черту с именем with_4_questions? ;)

Основываясь на этом опыте, я бы посоветовал вам начать с создания отдельных моделей в ваших спецификациях и сохранить их простыми. Не абстрагируйте излишнюю логику обратных вызовов.

Итак, скажем, что я пишу спецификацию функции, используя вашу модель. Это как бы я делать то, что вы пытаетесь достичь:

feature 'User edits a question' do 
    let!(:quiz) { FactoryGirl.create(:quiz) } 

    before do 
    5.times { FactoryGirl.create(:question, quiz: quiz) } 
    end 

    scenario 'with valid input' do 
    # ... 
    end 
end 

Если вы обнаружили, нуждающихся в quiz с 5 question s часто, вы можете создать macro с помощью метода, который Railscasts демонстрирующее. По крайней мере, тогда вы можете создать метод, в который вы можете передать параметры, например num_questions из моего полностью гипотетический вопрос выше.

+0

Спасибо, это действительно полезно! – Paul

+0

Я опубликовал другой подход, который также отвечает на ваш совершенно гипотетический вопрос по-другому. – fivedigit

4

Я предпочитаю использовать черты, поскольку они делают характеристики менее загроможденными. Конечно, важно убедиться, что сами фабрики не слишком захламлены.

Каждый раз, когда я определяю черту, которая строит ассоциацию, я убедиться, что я могу построить переменное количество записей в ассоциации, которая FactoryGirls позволяет сделать довольно легко:

FactoryGirl.define do 
    factory :quiz do 
    description 'Test' 

    trait :with_questions do 
     ignore { question_count 5 } 
     questions { build_list(:question, question_count) } 
    end 
    end 
end 

Теперь вы можете построить или создать в вашей викторину спецификации:

FactoryGirl.create(:quiz, :with_questions) 
FactoryGirl.build(:quiz, :with_questions, question_count: 2) 

Обратите внимание, что свойство использует build_list, так что не сохраняются вопросов по умолчанию, и question_count, а не questions_count так, чтобы он никогда не будет конфликтовать с противотоком КК Хин.

Чтобы убедиться, что ваши спецификации не делают больше, чем они могли бы, я бы не собирал вопросы с ответами, а скорее просто вопросы (если только ваши проверки не требуют их). Если в какой-то момент вам нужны вопросы с ответами, вы можете добавить еще одну особенность:

FactoryGirl.define do 
    factory :quiz do 
    description 'Test' 

    ignore { question_count 5 } 
    trait :with_questions do 
     questions { build_list(:question, question_count) } 
    end 

    trait :with_answered_questions do 
     questions { build_list(:question, question_count, :with_answers) } 
    end 
    end 
end 

Для получения дополнительной информации об использовании ассоциаций с FactoryGirl см FactoryGirl documentation.

+1

Похоже, что 'ignore' теперь' переходный 'в factorygirl https://github.com/thoughtbot/factory_girl/pull/651 – tgf

Смежные вопросы