16

I have the following rake task defined in my lib/tasks folder:

namespace :db do
  namespace :test do
    task :prepare => :environment do
      Rake::Task["db:seed"].invoke
    end
  end
end

Now, what this does is seed the test DB when I run rake db:test:prepare. I do this because I have some basic records that must exist in order for the app to function, so they're not optional and can't really be mocked.

Separately, I have a model that uses S3 for asset storage in development and production, but I don't want it to use S3 for testing. I have set up a method in the model that changes the storage path from S3 to local if Rails.env.test?

However, this isn't working. I was wondering if the rake task was aware of what environment it was being called from, and it turns out it is NOT. I put this at the top of my seeds.rb file:

puts "Environment Check: Rails Environment = #{Rails.env}"

Sure enough, when the task runs this prints: Environment Check: Rails Environment = development

So, how can I redo this rake task so that when it's seeding the test DB it knows that it's seeding the test DB??

Andrew
  • 42,517
  • 51
  • 181
  • 281
  • That would be really odd if `Rails.env` isn't giving you the correct value. Look elsewhere (how/what you're calling ). – Zabba Apr 03 '11 at 00:56
  • Honestly, nothing else. I type `rake db:test:prepare` into the console, and when it hits the seed task it puts `environment=development`. – Andrew Apr 03 '11 at 01:40

2 Answers2

15

I was having this problem too; in my db/seeds.rb file I have a block that creates user accounts in the development environment, but they were also being created when preparing the test environment to run rake for RSpec or Cucumber testing, which resulted in a wall of red.

Updated: I've found that the best way to specify the environment for rake tasks is to specify the environment within the task, above all statements that need the environment to be set. So in this case:

Rails.env = 'test'
Rake::Task["db:seed"].invoke

does the job.

jbhannah
  • 421
  • 2
  • 7
  • 1
    This is great -- much better than remembering to set the environment in the command line each time. Thanks! – Andrew Apr 29 '11 at 22:18
  • That was what drove me to try my original method--I couldn't stand having to put `RAILS_ENV=test` before every `rake` command. Setting the environment as an argument to `invoke` works if you only have the one task to run, but setting it at the start of the preparation block works best. – jbhannah Apr 29 '11 at 22:21
  • 1
    Note that merely setting the Rails environment prior to invoking the task is not sufficient to load fixtures from environment-specific folders. This is because seed_fu initializes the fixture paths when rake is first loaded prior to `Rails.env = 'test'`. To overcome, add a line after `Rails.env = 'test'` that says: `ENV["FIXTURE_PATH"] = Rails.root.join('db/fixtures').to_s`. This will cause seed_fu to recalculate the fixture paths using the `test` environment rather than the `development` environment under which you first execute the rake command. – Nathan Aug 21 '12 at 21:23
  • 1
    The above comment also applies when using [seedbank](https://github.com/james2m/seedbank). Then you'd probably want to invoke `db:seed:test` as `db:seed` would run your development seeds. – lime May 22 '14 at 12:04
8

From reading the db:test tasks's source, it looks like they only care about grabbing the test db info from database.yml, but don't care which actual environment they're doing it under.

You might need to run rake db:test:prepare RAILS_ENV=test to ensure you're under the test environment.

oliverbarnes
  • 2,111
  • 1
  • 20
  • 31