2012-07-18 4 views
6

Chcę wysychają po tworzyć/budować haki w moim fabryczne:DRY FactoryGirl po stworzyć/zbudować haki

FactoryGirl.define do 

    factory :poll do 

    sequence :title do |n| 
     "MyPollTitle#{n}" 
    end 
    sequence :description do |n| 
     "MyPollDescription#{n}" 
    end 
    user 

    factory :poll_with_answers do 

     ignore do 
     answers_count 2 
     end 

     after(:build) do |poll, evaluator| 
     evaluator.answers_count.times do 
      poll.answers << build(:answer, poll: poll) 
     end 
     end 

     after(:create) do |poll, evaluator| 
     evaluator.answers_count.times do 
      poll.answers << create(:answer, poll: poll) 
     end 
     end 
    end 
    end 
end 

Problem został skierowana jest to, że wydaje się, że nie można zdefiniować metody w FG? Pomysł, jak to SUCHYĆ?

Odpowiedz

6

Po pierwsze, after(:create) niejawnie wywołuje after(:build), przynajmniej w ostatnich wersjach FactoryGirl:

po (: build) - zwane po fabrycznym jest zbudowany (przez FactoryGirl.build, FactoryGirl.create)

https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#callbacks

Więc w twoim przypadku, następujący kod powinien być wystarczający:

after(:build) do |poll, evaluator| 
    evaluator.answers_count.times do 
    poll.answers << build(:answer, poll: poll) 
    end 
end 

Jednak after(:build) nie jest wyzwalany podczas korzystania build_stubbed() zamiast build(), co jest, co starałem się robić, kiedy natknąłem tego wątku. Aby DRY up tego kodu, okazuje się, można użyć metody callback(), aby wywołać ten sam blok dla wielu metod:

factory :user do 
    callback(:after_build, :after_stub) do |user| 
    do_something_with(user) 
    end 
end 
1

Może to być tani chwyt, ale można utworzyć lambda w drugiej fabryce:

factory :poll_with_answers do 
    ignore do 
    answers_count 2 
    end 

    make_answers = lambda do |poll, evaluator, method| 
    evaluator.answers_count.times do 
     poll.answers << send(method, :answer, poll: poll) 
    end 
    end 

    after(:build) do |poll, evaluator| 
    make_answers.call poll, evaluator, :build 
    end 

    after(:create) do |poll, evaluator| 
    make_answers.call poll, evaluator, :create 
    end 
end 

Nie jestem w ogóle zadowolony z tego wzoru, ale przynajmniej suchy za rzeczy w górę.

+0

To powinno wystarczyć. Jest to odpowiednik twojego kodu, więc jeśli ewaluator jest zerowy w wersji lambda, to powinien też być zerowy w twojej wersji. Czy możesz podać mi zarówno oryginalny działający kod i kod, który pobiera nils (również stacktrace). Nie mam wystarczających informacji do debugowania. –

+0

Nie musisz inwestować w to więcej pracy, nie ma to większego znaczenia, po prostu chciałem tylko sprawdzić, czy jest skrót. W każdym razie zrobiłem sedno na https://gist.github.com/3140033, gdzie można zobaczyć modele, reszta to 1: 1. – wintersolutions

+0

Cóż, nie martw się, ale po sprawdzeniu kodu, nie mam pojęcia, czym jest "oceniający" :) –