Rails: Different storage for carrierwave assets depending on the environment

I am using carrierwave for storing images, one (or more) per field of a table in a database of the my Rails app. Given that heroku does not allow assets to be uploaded by the user, or dynamically for that matter, I had to use storage in the cloud. Mind you, not a bad thing. I chose AWS, s3 services to store my bucket.

Carrierwave has an extensive explanation on setting up the right configuration variables to allow the storage on the cloud. (Carrierwave in github)

The first problem I had was running the development and staging (or production) sites at the same time: Updates in one were seen in the other in the following case:

  1. Create a field with id=1 in production. The image associated with it, is stored in the cloud with id=1.
  2. Create a field with id=1 in development. the image associated with it, overrides in the cloud, the previously created image.

My solution to solve this problem was to create a second bucket, and add in the file

config/initialize/carrierwave.rb

the setting as follows:

# config/initialize/carrierwave.rb
...
  if Rails.env.production?
    config.fog_directory = 'bucket-0'
  elsif Rails.env.development?
    config.fog_directory = 'bucket-1'
  end

The next problem was that the test suite run was affecting the development data in the same way as described before. In fact, I wanted the images for the test suites simply to be stored locally and then deleted. The first approach was to include in the same file as above the following:

# config/initialize/carrierwave.rb
...
  if Rails.env.test? || Rails.env.cucumber?
    config.storage = :file
    config.enable_processing = false
    config.root = "#{Rails.root}/tmp"
  else
    config.storage = :fog
  end

  config.cache_dir = "#{Rails.root}/tmp/uploads"

And to delete after finishing the test, add to the file:

spec/spec_helper.rb

the following:

# spec/spec_helper.rb
RSpec.configure do |config|
  config.after(:all) do
    if Rails.env.test?
      FileUtils.rm_rf(Dir["#{Rails.root}/tmp/uploads"])
    end
  end
end

That only seemed to work. I think that the display was using cache data. Only recently did I notice the problem when reworking some aspects of the app. The images in development were being overwritten by the test suite.

I had to add the following to the uploader file

# app/uploaders/image_uploader.rb
...
  if Rails.env.test?
    storage :file
  else
    storage :fog
  end

Et voilá!

Leave a comment