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
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
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
--fixture-replacement
?
rails g model
, not for a magic factory-creation using the model description in the schema for example. This option was discussed here: github.com/thoughtbot/factory_girl_rails/issues/63. @edouardo-santana and @cjhveal answers are both acceptable.
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
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.
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
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.
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.
不定期副业成功案例分享
spec
directory?rails g factory_girl:model User --dir spec/factories