nicholas79171
nicholas79171

Reputation: 1273

How do I seed my database with only part of my seed code?

Is it possible to run one or two blocks within my seeds.rb code like you can with tests and gemfiles?

For example, if I had the following code in my seeds.rb file, could I just seed the Employee model?

20.times do
  Employee.create!(name: "Bob",
                   email: Faker::Internet.email)
end

20.times do
  User.create!(name:     "Hank",
               password: "foobar") 
end

If this were my entire seeds.rb file, running rake db:seed would create 20 additional users when I only want to add more employees.

Upvotes: 1

Views: 3831

Answers (2)

Philip Hallstrom
Philip Hallstrom

Reputation: 19879

I've used the following setup for a couple of years now to help my sanity.

In db/seeds I have the following files:

001_providers.rb
005_api_users.rb
007_mailing_lists.rb
010_countries.rb
011_us_states.rb
012_canadian_provinces.rb
013_mexican_states.rb
100_world_cities.rb
101_us_zipcodes.rb

My db/seeds.rb file looks like this:

if ENV['VERSION'].present?
  seed_files = Dir[File.join(File.dirname(__FILE__), 'seeds', "*#{ENV['VERSION']}*.rb")]
  raise "No seed files found matching '#{ENV['VERSION']}'" if seed_files.empty?
else
  seed_files = Dir[File.join(File.dirname(__FILE__), 'seeds', '*.rb')]
end

seed_files.sort_by{|f| File.basename(f).to_i}.each do |file|
  require File.join(File.dirname(__FILE__), 'seeds', File.basename(file, File.extname(file)))
end

Just a bit of ruby code to let me run one or more seed files. I can now do things like this:

# run them all
bin/rake db:seed

# run just 001_providers.rb
bin/rake db:seed VERSION=001

# run all seeds for the USA (probably dangerous, but if you name your seeds right, could be useful). 
bin/rake db:seed VERSION=us

One thing that is very important is that your seed files should be able to be run over and over and over and end up with a consistent state. If you run your seeds over and over you'll end up with many more users than just 20.

For example, my providers one has a main loop like this:

# providers is a hash of attributes...
providers.each_with_index do |(code, attrs), i|
  p = Provider.find_by(code: code) || Provider.new(code: code)       p.update!(attrs)
end

This way regardless of when I run it, I always get back exactly the providers I defined in my hash.

Upvotes: 3

Arslan Ali
Arslan Ali

Reputation: 17802

You can pass an option while running rake db:seed like following:

rake db:seed users=yes

And, then in your code, you can access it through the following way:

20.times do
  Employee.create!(name: "Bob",
                   email: Faker::Internet.email)
end

if ENV["users"]
  20.times do
    User.create!(name:     "Hank",
                 password: "foobar") 
  end
end

Upvotes: 5

Related Questions