factory_bot
factory_bot copied to clipboard
Underscores being removed from class name during tests
Description
hey team 👋🏻
I'm currently trying to move away from defining the class attribute as a class to a string. The thing is, in this project, for different reasons, some classes have an underscore in their names. That is not going to change and it is like that for different reasons.
Currently some factories are defined like this:
factory :customs_declaration_nl_ddu_1, class: Customs::Declarations::NL::DDU_1_0
When I correct to String, like this
factory :customs_declaration_nl_ddu_1, class: "Customs::Declarations::NL::DDU_1_0"
errors like below start to pop up:
Failure/Error: products: build_list(:customs_product_ddu, 1))
NameError:
uninitialized constant Customs::Products::NL::DDU10
Reproduction Steps
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 "sqlite3"
end
require "active_record"
require "factory_bot"
require "minitest/autorun"
require "logger"
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Schema.define do
# TODO: Update the schema to include the specific tables or columns necessary
# to reproduct the bug
create_table :posts, force: true do |t|
t.string :body
end
end
# TODO: Add any application specific code necessary to reproduce the bug
class Post_3_D < ActiveRecord::Base
self.table_name = "posts"
end
FactoryBot.define do
# TODO: Write the factory definitions necessary to reproduce the bug
factory :post, class: "Post_3_D" do
body { "Post body" }
end
end
class FactoryBotTest < Minitest::Test
def test_factory_bot_stuff
# TODO: Write a failing test case to demonstrate what isn't working as
# expected
body_override = "Body override"
post = FactoryBot.build(:post, body: body_override)
assert_equal post.body, body_override
end
end
Expected behavior
Underscores are not to be removed from the class name
Actual behavior
System configuration
factory_bot version: 6.2.0 rails version: 7.0.6 ruby version: 3.2.2
That's happening because of a call to camelize https://github.com/thoughtbot/factory_bot/blob/4a37cb64090d6354a719e8c5ef73653f5d242017/lib/factory_bot/factory.rb#L26. It might be tricky to handle that without breaking other cases (we could maybe skip camelize if there are already capital letters? But it's bound to break something for somebody). The only workaround at the moment is continuing to use the contant instead of a string 😢.
I see the problem...out of curiosity, why is camelize being called anyway? According to the docs you can either pass the class name as String or the class itself. In both cases to_s.constantize should be sufficient, no? What are other people doing that require a call to camelize?
"namespace/model".camelize => "Namespace::Model"
ah so "namespace/model" is a valid class parameter then
I understand that our use case might be too specific and it's not worth updating the library to solve an edge case like this. If you think there is something of value here, it is fine otherwise, I think this can be closed.
I appreciate the help!
@luizkowalski a bit late, but we were able to resolve this issue in https://github.com/thoughtbot/factory_bot/pull/1642. hope this helps your use case!
thanks a lot, that's great!