How to use FactoryGirl factories to build a development database?
Asked Answered
G

2

11

I have already built some elaborate FactoryGirl factory definitions for testing a Rails project, and for this purpose they are working well.

I'd now like to use the same definitions with a script (Ruby, Rake, whatever...) to populate the Rails development database with a large collection of valid, correctly associated records.

I'm sure this is a common task but cannot find a useful reference.

What is best practice? How to proceed?

Say the factories are in spec/factories.rb. What next? Thanks.

Update

Still struggling. Tried this as a rake task.

require 'factory_girl'
require 'spec/factories'

namespace :db do
  desc "Fill database with trial data"
  task :populate => :environment do
    Rake::Task['db:reset'].invoke
    50.times do |n|
      # Make a consistent set of related records.
      team = FactoryGirl.create(:team, :completed)
      team.members << FactoryGirl.create(:member)
      FactoryGirl.create(:design, :team => team)
    end
  end
end

Alas, this can't find my factories.rb:

rake aborted!
cannot load such file -- spec/factories

Everywhere else a project root-relative require path works fine. What is the secret handshake?

Galitea answered 3/4, 2013 at 2:12 Comment(9)
This is typically the work of the seeds file. Is there a reason you don't want to use seeds to populate your DB?Teapot
Never heard of seeds. Can you provide a reference, please? (Most days learning Rails seems like a scavenger hunt...)Galitea
@Galitea railscasts.com/episodes/179-seed-dataContrariwise
@ChrisSchmitz Thanks a lot. This looks more like it's used to install base data required for the application to run than for just providing some records to check see if implementation strategy is working out, which is my purpose. But I'll study it.Galitea
Did you by any chance put the gem factory_girl in the group test only ? If so, it has to be in development also in order to use it like you want to.Helli
I put it in the project Gemfile and bundle installed it. I'm sorry I don't know what group test means. Thanks for the help.Galitea
Never seen factories used to populate a database with sample data. I would suggest having a look here at the Rails Tutorial for an example of a script that will populate a database with randomized data.Brayton
@PaulFioravanti I'm very familiar with the tutorial. But creating randomized records in my app is far less trivial than its example app. The logical already exists for my app in a set of testing factories, which already create pseudo-random records. Re-implementing would be very un-DRY.Galitea
@Helli Sorry I did not get the term "groups" as Gemfile config groups. Indeed I had factory_girl in test only. Will move and try.Galitea
T
1

As I mentioned in my comment, this is typically the work of seed data. If you want this data to only be seeded into your development database, you could modify the seed Rake task by doing something like this:

namespace :db do
  task :seed => :environment do
    env_seed_file = File.join(Rails.root, 'db', 'seeds', "#{Rails.env}.rb")
    load(env_seed_file) if File.exist?(env_seed_file)
  end
end

which would give you the ability to create a file for each environment (i.e. db/seeds/development.rb). You could also use a gem like seedbank which gives you environment specific seed files and a few other additions to what's already in Rails.

Teapot answered 3/4, 2013 at 13:31 Comment(2)
Thanks. In the seeds.rb file as you said I have the full environment load path for require, so FactoryGirl and my factory defs work fine. I just wrapped my code in if Rails.env == 'development' to ensure it doesn't generate random records in non-development databases. I'll use your more general solution later if a more complex requirement appears.Galitea
I just found this answer while looking how to generate test data with factory_girl. Seeding a database is usually not at all used for adding test data to a database but to seed initial records in development and production. (See here and here)Penknife
M
0

@Gene You were close to solve this puzzle. I think you were one path away from this. I'm not using RSpecs and the path could differ slightly, but you got the general idea.

namespace :db do
  desc "Fill database with trial data"
  task :populate => :environment do
    require 'factory_girl'
    require Rails.root + 'spec/factories'

    Rake::Task['db:reset'].invoke
    Rake::Task['db:seed'].invoke
    50.times do |n|
      # Make a consistent set of related records.
      team = FactoryGirl.create(:team, :completed)
      team.members << FactoryGirl.create(:member)
      FactoryGirl.create(:design, :team => team)
    end
  end
end

I only precise you path for the required factory file and I also add the rake db:seed after your reset.

The DB seed is not to fill you database at the development time, but bootstrap your new application with the proper information to be able to work normally. ie. Creating an admin user and default status

Medicine answered 12/3, 2015 at 20:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.