Can FactoryBot generate factories after your models have been created?
Asked Answered
W

9

62

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

Wooten answered 28/7, 2012 at 15:22 Comment(2)
What exactly do you mean with "generating"? You have to define and call them explicitly.Stinker
@Stinker - I mean when you use the "factory_girl_rails" gem, when you generate your models via command as "rails g model User first_name:string"... etc. factories for this model are auto-generated just as a fixture is for testing. I was wondering if there was a way to use a generator hook after the model has been created.Wooten
P
179

First thing, look at the source project to find out how it was implemented:

https://github.com/thoughtbot/factory_bot_rails/blob/master/lib/generators/factory_bot/model/model_generator.rb

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

Penetrating answered 5/2, 2013 at 0:8 Comment(5)
This should be the correct answer, because it answers the specific question about how to generate factories for models that have already been created. The common scenario is switching an existing rails app with default fixtures to using FactoryGirlRainer
you don't even have to guess how it works, rails g factory_girl:model --help will tell you how.Serenity
Any way to create it under spec directory?Ditchwater
@Ditchwater you can specify with --dir option. rails g factory_girl:model User --dir spec/factoriesHectorhecuba
There is also a way to do it using schema_to_scaffold gem. It will print the factory_bot:model script with all the fields/columns of the table. See my answer belowMeanie
F
21

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

Source: https://github.com/thoughtbot/factory_bot_rails/blob/master/features/fixture_replacement_config.feature#L21

Felucca answered 28/7, 2012 at 22:32 Comment(8)
That does the trick! It's amazing what you'll find when you just read through the documentation. :)Wooten
How does this answer the question ? How does it generate factories after the models were created ?Degeneracy
See answer from user2040729 below.Rainer
To get this to work with rspec in Rails 4.1, I needed to write: g.fixture_replacement :factory_girl, dir: "spec/factories"Reunite
Your answer is not related to the question had been askedFruitless
Who is user2040729? how this answer the question? how to use --fixture-replacement?Nardi
There's a great misunderstanding here. @Wooten was asking for the generator command called after a 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 @Felucca answers are both acceptable.Urbain
Eduardo Santana's ANSWER SHOULD BE CORRECTVola
M
10

I have a gem for exactly this https://github.com/markburns/to_factory

Money answered 8/1, 2015 at 15:12 Comment(0)
H
9

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 updated_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
Heavensent answered 13/5, 2018 at 18:12 Comment(2)
This Answer must be the right answer which generates factories from DB. Awesome!! KudosKumquat
Careful with this script, @force = true by defaultTrebuchet
C
4

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

For more: https://github.com/thoughtbot/factory_bot_rails/blob/master/features/fixture_replacement_config.feature

Countercurrent answered 31/10, 2019 at 13:35 Comment(0)
M
3

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.

Check here or here

Meanie answered 17/5, 2013 at 19:55 Comment(0)
H
0

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.

Hands answered 19/9, 2021 at 10:8 Comment(0)
M
0

Another option is to gem install schema_to_scaffold and then run scaffold -f

It will print the rails generator script to create the factory with all the fields for the table. Then you can copy paste the script and run it.

Meanie answered 31/7, 2023 at 12:37 Comment(0)
P
-1

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.

Picofarad answered 23/1, 2014 at 21:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.