I want to DRY up the after create/build hooks in my Factory:
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
The problem I was facing is that it seems I can't define methods in FG? Idea how to DRY this up?
Firstly, after(:create)
implicitly calls after(:build)
, at least in recent versions of FactoryGirl:
after(:build) - called after a factory is built (via FactoryGirl.build, FactoryGirl.create)
https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#callbacks
So in your case, the following code should be sufficient:
after(:build) do |poll, evaluator|
evaluator.answers_count.times do
poll.answers << build(:answer, poll: poll)
end
end
However, after(:build)
isn't triggered when you use build_stubbed()
instead of build()
, which is what I was trying to do when I came across this thread. To DRY up this code, it turns out you can use the callback()
method to call the same block for multiple methods:
factory :user do
callback(:after_build, :after_stub) do |user|
do_something_with(user)
end
end
This might be a cheap trick, but you can create a lambda in the second factory:
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
I'm not at all happy with this pattern, but at least it DRY's stuff up.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With