3

I have seeds.rb populating my development database. And I know I can easily apply seeds.rb to my test database using:

rake db:seed RAILS_ENV=test

However, I want a different seeds.rb file to populate my test database. Maybe seeds_test.rb. This must be an extremely common requirement among rails programmers, isn't it?

If there's no easy way to do this, like rake db:seed:seeds_test RAILS_ENV=test, then how would I create a rake task? I would think something like this in lib/tasks/test_seeds.rake:

namespace :db do
  desc "Seed data for tests"
  task :seed_test => :environment do
    load "#{Rails.root}/db/seeds_test.rb"
  end
end

I think that'll work, but then I would love for my rake task to automatically know to apply this only to the test database without me having to specify:

rake db:seed_test RAILS_ENV=test

How do I get the rake task so all I have to enter in the command line is:

rake db:seed_test

UPDATE: Another stackoverflow question was linked to where the answer was to do this:

Rails.env = 'test'

Unfortunately that doesn't actually do anything (at least as of Rails 4.2) :(.

at.
  • 50,922
  • 104
  • 292
  • 461
  • possible duplicate of [Rails: Make this rake task aware that it is in the test environment](http://stackoverflow.com/questions/5525757/rails-make-this-rake-task-aware-that-it-is-in-the-test-environment) – Amadan Jan 13 '15 at 01:21
  • Unfortunately that answer to that duplicate question (which is not really a duplicate) doesn't work :(. `Rails.env = 'test'` doesn't actually change the environment and the seed data goes into the development database. – at. Jan 13 '15 at 01:29
  • Doesn't it? I just tested it, and it definitely works for me (data added to `test.sqlite3` only). (I copied your code, put `Rails.env = 'test'` just above `load`.) I also run Rails 4.2.0. – Amadan Jan 13 '15 at 01:39
  • 1
    Loading test data is an extremely common requirement. The most common approach is to use fixtures for test data. Why not use fixtures and `rake db:fixtures:load`? – blowmage Jan 13 '15 at 04:04
  • @Amadan - I enthusiastically tried this `Rails.env = 'test'`, but it loaded the data to the `development.sqlite3` database only, not the `test.sqlite3` database. Leading me to question what purpose the `Rails.env = 'test'` statement had. @blowmage, fixtures seems to make sense, I just keep reading how fixtures should never be used... – at. Jan 13 '15 at 09:42
  • @at. have you tried http://stackoverflow.com/questions/19872271/adding-a-custom-seed-file ? – basiam Jan 13 '15 at 13:44
  • @BasiaMadej - that's not my issue. I want to force the rake task to use the test database or test environment. – at. Jan 14 '15 at 07:40

2 Answers2

12

In db/seeds.rb, test for the value of Rails.env and execute the respective seeding:

#db/seeds.rb
case Rails.env
when 'development'
  # development-specific seeds ...
  # (anything you need to interactively play around with in the rails console)

when 'test'
  # test-specific seeds ...
  # (Consider having your tests set up the data they need
  # themselves instead of seeding it here!)

when 'production'
  # production seeds (if any) ...

end

# common seeds ...
# (data your application needs in all environments)

If you want to use separate files, just require them inside this structure, e.g.:

#db/seeds.rb
case Rails.env
when 'development'
  require 'seeds_development'    
when 'test'
  require 'seeds_test'
when 'production'
  require 'seeds_production'
end

require 'seeds_common'

or shorter

#db/seeds.rb
require "seeds_#{Rails.env}"
require 'seeds_common'
das-g
  • 9,718
  • 4
  • 38
  • 80
  • This isn't my issue. I want to always write to my test database. – at. Jan 15 '15 at 23:48
  • Oh, I thought defining a custom `rake` task to write test-specific seeds to your test database was only what you were looking to do _if there was no easy way_ to have `rake db:seed RAILS_ENV=test` write test-specific seeds to your test database. – das-g Jan 16 '15 at 00:16
  • You need to use double quotes for string interpolation: `require "seeds_#{Rails.env}"` – Victor Hugo Bueno Nov 01 '17 at 01:36
  • @VictorHugoBueno thanks for the heads-up. Fixed now. – das-g Nov 02 '17 at 09:34
0

If you are using spring, you can set a Rails environment for a rake task:

# config/spring.rb
Spring::Commands::Rake.environment_matchers['db:seed_test'] = "test"

or for all tasks matching a regex pattern:

# config/spring.rb
Spring::Commands::Rake.environment_matchers[/^db:.+_test$/] = "test"

This allows you to call

rake db:seed_test

and have it run in the test Rails environment, thus writing to your test DB.

However, this doesn't have any effect

  • if spring isn't used for rake
    or
  • if the rake task isn't invoked directly (e.g. from the command line) but as a dependency of another rake task not matching the pattern
das-g
  • 9,718
  • 4
  • 38
  • 80