The factory_bot documentation for build strategies says:
factory_bot supports several different build strategies: build, create, attributes_for and build_stubbed
And continues with some examples of usage. However, it doesn't clearly state what the result of each one is. I've been using create
and build
for a while now. attributes_for
seems straightforward from the description and I see some uses for it. However, what is build_stubbed
? The description says
Returns an object with all defined attributes stubbed out
What does "stubbed out" mean? How is this different from either create
or build
?
CodePudding user response:
Let's consider the difference on the example of these factories:
FactoryBot.define do
factory :post do
user
title { 'Post title' }
body { 'Post body' }
end
end
FactoryBot.define do
factory :user do
first_name { 'John' }
last_name { 'Doe' }
end
end
build
With build
method everything is easy. It returns a Post
instance that's not saved
# initialization
post = FactoryBot.build(:post)
# call
p post
p post.user
# output
#<Post:0x00007fd10f824168> {
:id => nil,
:user_id => nil,
:title => "Post title",
:body => "Post body",
:created_at => nil,
:updated_at => nil
}
#<User:0x00007f8792ed9290> {
:id => nil,
:first_name => "Post title",
:last_name => "Post body",
:created_at => nil,
:updated_at => nil
}
Post.all # => []
User.all # => []
create
With create
everything is also quite obvious. It saves and returns a Post
instance. But it calls all validations and callbacks and also creates associated instance of User
# initialization
post = FactoryBot.create(:post)
# call
p post
p post.user
# output
#<Post:0x00007fd10f824168> {
:id => 1,
:user_id => 1,
:title => "Post title",
:body => "Post body",
:created_at => Sat, 18 Jun 2022 05:32:17.122906000 UTC 00:00,
:updated_at => Sat, 18 Jun 2022 05:32:17.122906000 UTC 00:00
}
#<User:0x00007f8792ed9290> {
:id => 1,
:first_name => "John",
:last_name => "Joe",
:created_at => Sat, 18 Jun 2022 05:32:17.122906000 UTC 00:00,
:updated_at => Sat, 18 Jun 2022 05:32:17.122906000 UTC 00:00
}
Post record and associated user record were created in the database:
Post.all # => [<Post:0x00007fd10f824168> {...}]
# User also created in the database
User.all # => [<User:0x00007f91af405b30> {...}]
build_stubbed
build_stubbed
imitates creating. It slubs id
, created_at
, updated_at
and user_id
attributes. Also it skips all validations and callbacks.
Stubs means that FactoryBot
just initialize object and assigns values to the id
created_at
and updated_at
attributes so that it just looks like created. For id
it assign integer number 1001
(1001 is just default number what FactoryBot uses to assign to id), for created_at
and updated_at
assigns current datetime. And for every other record created with build_stubbed
is will increment number to be assigned to id by 1.
First FactoryBot
initialize user
record and assign 1001
to id
attribute but not save it to the database than it initialize post
record and assing 1002
to the id
attribute and 1001
to user_id
attribute to make association, but also doesn't save record to the database.
See example below.
#initialization
post = FactoryBot.build_stubbed(:post)
# call
p post
p post.user
# output
# It looks like persisted instance
#<Post:0x00007fd10f824168> {
:id => 1002,
:user_id => 1001,
:title => "Post title",
:body => "Post body",
:created_at => Sat, 18 Jun 2022 05:32:17.122906000 UTC 00:00,
:updated_at => Sat, 18 Jun 2022 05:32:17.122906000 UTC 00:00
}
#<User:0x00007f8792ed9290> {
:id => 1001,
:first_name => "John",
:last_name => "Joe",
:created_at => Sat, 18 Jun 2022 05:32:17.122906000 UTC 00:00,
:updated_at => Sat, 18 Jun 2022 05:32:17.122906000 UTC 00:00
}
Post and user records were not created in the database!!!
# it is not persisted in the database
Post.all # => []
# Association was also just stubbed(initialized) and there are no users in the database.
User.all # => []