Can FactoryBot generate factories after your models have been created?
Ruby on-RailsRubyFactory BotRuby on-Rails Problem Overview
When including the factory_bot_rails gem in your dev and test blocks in Gemfile, rails will generate factories automatically when your models are generated.
Is there a way to generate factories after your models have been generated?
Note: FactoryBot was previously named FactoryGirl
Ruby on-Rails Solutions
Solution 1 - Ruby on-Rails
First thing, look at the source project to find out how it was implemented:
After that, try to guess how it works:
rails g factory_bot:model Car name speed:integer
The result is:
create test/factories/cars.rb
And the content:
# Read about factories at https://github.com/thoughtbot/factory_girl
FactoryBot.define do
factory :car do
name "MyString"
speed 1
end
end
Remember, when you use rails g, you can always undo it, with rails d
rails d factory_bot:model Car name speed:integer
Note: FactoryBot was previously named FactoryGirl
Solution 2 - Ruby on-Rails
The --fixture-replacement
option will let you tell rails what to generate for building test data. You can set this as a default in your config/application.rb
file, like so:
config.generators do |g|
g.fixture_replacement :factory_bot, suffix_factory: 'factory'
end
Solution 3 - Ruby on-Rails
I have a gem for exactly this https://github.com/markburns/to_factory
Solution 4 - Ruby on-Rails
This works for me using rails g factory_bot:model User either running the command or just puts'ing the command out. You do still have to fill in the value.
@run_command = true
@force = true
@columns_to_ignore = %w[id created_at update_at]
@tables_to_ignore = %w[schema_migrations ar_internal_metadata]
tables = ActiveRecord::Base.connection.tables.reject{|t| (@tables_to_ignore || []).include?(t)}
tables.each do |table|
klass = table.singularize.camelcase.constantize
command = "rails g factory_bot:model #{klass.to_s} #{klass.columns.reject do |c|
(@columns_to_ignore || []).include?(c.name)
end.map do |d|
"#{d.name}:#{d.sql_type == 'jsonb' ? 'json' : d.type}"
end.join(' ')}"
command << ' --force' if @force
puts command
puts %x{#{command}} if @run_command
puts (1..200).to_a.map{}.join('-')
end
Solution 5 - Ruby on-Rails
This is not an answer, but since I cannot comment yet: I think you can use this to solve part of your problem. You can use a gem called schema_to_scaffold to generate a factory_girl:model command string. It outputs:
rails generate factory_girl:model users fname:string lname:string bdate:date email:string encrypted_password:string
from your schema.rb or your renamed schema.rb.
Solution 6 - Ruby on-Rails
Configure Factory Bot as the fixture replacement so you do not have to create factories manually.
In config/application.rb
:
config.generators do |g|
g.test_framework :rspec, fixture: true
g.fixture_replacement :factory_bot, dir: 'spec/factories'
end
Solution 7 - Ruby on-Rails
Not exactly related.
I also built a gem to build factory from existing data.
Hopefully, it can help you speed up the process a bit......
puts FactoryBotFactory.build(User.new, file_path: 'spec/factories/user.rb')
puts FactoryBotFactory.build(User.last, file_path: 'spec/factories/user.rb')
# example output from User.new
FactoryBot.define do
factory :user, class: User do
id { nil }
name { nil }
created_at { nil }
updated_at { nil }
display_name { nil }
image_url { nil }
is_active { true }
end
end
You can also configure customize converter if you need to built fake data.
Solution 8 - Ruby on-Rails
Some good answers here, but another option is to use stepford. For some projects that use schemas that have foreign key constraints, the deep_* methods, etc. might help, and it is a simple way to generate factories via command-line.