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

Alter Lagos
  • 12,090
  • 1
  • 70
  • 92
GuiDoody
  • 897
  • 1
  • 6
  • 13
  • What exactly do you mean with "generating"? You have to define and call them explicitly. – iltempo Jul 28 '12 at 15:54
  • @iltempo - 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. – GuiDoody Jul 28 '12 at 17:45

9 Answers9

177

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

Jai Chauhan
  • 4,035
  • 3
  • 36
  • 62
Eduardo Santana
  • 5,780
  • 3
  • 19
  • 21
  • 12
    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 FactoryGirl – Shyam Habarakada Mar 03 '13 at 18:20
  • 2
    you don't even have to guess how it works, rails g factory_girl:model --help will tell you how. – Les Nightingill Jun 23 '13 at 22:44
  • 6
    Any way to create it under `spec` directory? – juliangonzalez Dec 03 '16 at 01:32
  • @juliangonzalez you can specify with --dir option. `rails g factory_girl:model User --dir spec/factories` – marman Oct 18 '17 at 15:50
  • 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 below – frenesim Jul 31 '23 at 12:42
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

BinaryButterfly
  • 18,137
  • 13
  • 50
  • 91
cjhveal
  • 5,668
  • 2
  • 28
  • 38
  • That does the trick! It's amazing what you'll find when you just read through the documentation. :) – GuiDoody Jul 29 '12 at 20:17
  • 22
    How does this answer the question ? How does it generate factories after the models were created ? – Emil Jan 24 '13 at 09:16
  • 1
    See answer from user2040729 below. – Shyam Habarakada Mar 03 '13 at 18:34
  • To get this to work with rspec in Rails 4.1, I needed to write: g.fixture_replacement :factory_girl, dir: "spec/factories" – ClaytonC Sep 02 '14 at 20:31
  • Your answer is not related to the question had been asked – Santi Apr 05 '16 at 16:00
  • 4
    Who is user2040729? how this answer the question? how to use `--fixture-replacement`? – Arnold Roa Apr 24 '16 at 10:58
  • 1
    There's a great misunderstanding here. @GuiDoody 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: https://github.com/thoughtbot/factory_girl_rails/issues/63. @edouardo-santana and @cjhveal answers are both acceptable. – fro_oo May 01 '16 at 13:52
  • [Eduardo Santana's ANSWER SHOULD BE CORRECT](https://stackoverflow.com/questions/11702265/can-factorybot-generate-factories-after-your-models-have-been-created/14698033#14698033) – João Souza Oct 02 '20 at 17:43
10

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

Mark Burns
  • 158
  • 2
  • 9
7

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
Davinj
  • 327
  • 4
  • 16
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

Kaka Ruto
  • 4,581
  • 1
  • 31
  • 39
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

frenesim
  • 703
  • 9
  • 10
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.

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.

frenesim
  • 703
  • 9
  • 10
-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.

Gary S. Weaver
  • 7,966
  • 4
  • 37
  • 61