factory_bot
factory_bot copied to clipboard
`build_stubbed` does not fill `id` for `uuid` column type
Description
When using uuid
as the primary key type, they build_stubbed
method does not automatically fill the id
column. I would assume that this is filled independent of the column type.
Reproduction Steps
Reproduction script
#!/usr/bin/env ruby
require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem "factory_bot", "~> 6.0"
gem "activerecord"
gem "pg"
end
require "active_record"
require "factory_bot"
require "minitest/autorun"
require "logger"
ActiveRecord::Base.establish_connection(adapter: "postgresql", database: "factory_bot_test")
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Schema.define do
enable_extension 'pgcrypto'
create_table :int_posts, force: true do |t|
t.string :body
end
create_table :uuid_posts, id: :uuid, force: true do |t|
t.string :body
end
end
class IntPost < ActiveRecord::Base
end
class UuidPost < ActiveRecord::Base
end
FactoryBot.define do
factory :int_post do
body { "Post body" }
end
factory :uuid_post do
body { "Post body" }
end
end
class FactoryBotTest < Minitest::Test
def test_working_with_int
post = FactoryBot.build_stubbed(:int_post)
refute_nil post.id
end
def test_failing_with_uuid
post = FactoryBot.build_stubbed(:uuid_post)
refute_nil post.id
end
end
# Run the tests with `ruby <filename>`
Expected behavior
When you use build_stubbed
, the primary key is always set. Also if you use the uuid
type.
Actual behavior
The id
of the generated instance is nil
.
System configuration
factory_bot version: 6.2.0
rails version: 6.1.3.2
ruby version: 3.0.1
Thanks for opening an issue @StefSchenkelaars . We did some exploration and it seems like an issue with the type of the column. This could be something we support, but the assumption made to auto-generate the primary_key
value is a self incrementing number, the class variable @@next_id
on the stub strategy. This is a good place to start if you're interested in exploring a bit more!
As a workaround, you could specify the id when the value is built, or you can try adding it on your factory definition.
post = FactoryBot.build_stubbed(:uuid_post, id: SecureRandom.uuid)
# Or on the definition
factory :uuid_post do
id { SecureRandom.uuid }
body { "Post body" }
end
I think a first action we could take is to add a note on the GETTING_STARTED.md doc, mentioning that the primary key stub only works for numeric primary keys.
A third workaround if you have a number of models with uuids, create a global trait with_id
, for easy removal once support lands:
# frozen_string_literal: true
# Temporary workaround for https://github.com/thoughtbot/factory_bot/issues/1498 until https://github.com/thoughtbot/factory_bot/pull/1583 is released.
# Once #1583 is released, remove this trait and use build_stubbed directly.
FactoryBot.define do
trait :with_id do
id { SecureRandom.uuid }
end
end