Blog

A Gentle Introduction to CarrierWave

By | August 18th, 2011 at 12:08PM
This guest post hails from community contributor Trevor Turk. Trevor is a chess-playing machine of the late 18th century, promoted as an automaton but later proved a hoax. Trevor tweets as @trevorturk and blogs too.

CarrierWave is self-described as a “classier solution for file uploads for Rails, Sinatra and other Ruby web frameworks.” Although I’ve head it referred to as “a new kid on the block” it’s actually quite an old gem. The initial checkin is from August 2008 and the first release was in March 2009. The original name was Merb::Upload and it started without support for Rails.

The fact that CarrierWave began its life as a Merb plugin may help explain its modularity, flexibility, and extensibility.

Thanks to fog, it has support for Amazon S3, Rackspace Cloud Files, and Google Storage for Developers. It also supports plain old file storage and MongoDB’s GridFS store. There’s ORM support available for ActiveRecord, Mongoid, DataMapper, Sequel, Mongo Mapper, CouchDB, and more. Image processors are available for RMagick, ImageScience, MiniMagick.

Let’s see this modularity first hand by building up a CarrierWave uploader from scratch.

To begin with, we’ll install CarrierWave:

  gem install carrierwave

Then, we can make the world’s shortest uploader:

  require 'carrierwave'
 
  class MyUploader < CarrierWave::Uploader::Base
    storage :file
  end

Even at this point, we can start saving files:

  file = File.open('example.jpg')
  uploader = MyUploader.new
  uploader.store!(file)

The uploader houses the logic for uploading files in self-contained classes, so this is all we need to get started.

It’s dead easy to store files on Amazon S3 with fog. First, install the fog gem:

  gem install fog

Then configure the fog_credentials and set the uploader’s storage to fog:

  CarrierWave.configure do |config|
    config.fog_credentials = {
      :provider               => 'AWS',
      :aws_access_key_id      => 'xxx',
      :aws_secret_access_key  => 'yyy'
    }
    config.fog_directory  = 'zzz'
  end
 
  class MyUploader < CarrierWave::Uploader::Base
    storage :fog
  end

Configuring fog to use Rackspace Cloud Files or Google Storage for Developers is so easy I hesitate to even mention it. This is all we’d need to change to use Rackspace:

  CarrierWave.configure do |config|
    config.fog_credentials = {
      :provider           => 'Rackspace',
      :rackspace_username => 'xxx',
      :rackspace_api_key  => 'yyy'
    }
    config.fog_directory = 'zzz'
  end

Suppose we want to have image thumbnails. First, we need to install RMagick:

  gem install rmagick

Then, we just add a version block to our uploader:

  require 'carrierwave'
  require 'rmagick'
 
  class MyUploader < CarrierWave::Uploader::Base     
    include CarrierWave::RMagick
    version :thumb do
      process :resize_to_fill => [200,200]
    end
 
    storage :file
  end

This has all been so easy, though. Let’s give ourselves a challenge and create an app that uses CarrierWave, Sinatra, and Sequel with SQLite.

To begin, we’ll need to install these new gems:

  gem install sinatra sqlite3 sequel carrierwave-sequel

Then, we’ll create the app. It’s so small (55 lines) that I’ll just include the whole thing here:

  require 'carrierwave'
  require 'sinatra'
  require 'sqlite3'
  require 'sequel'
  require 'carrierwave/sequel'
 
  # database setup
 
  DB = Sequel.sqlite
 
  DB.create_table :uploads do
    String :file
  end
 
  # uploader
 
  class MyUploader < CarrierWave::Uploader::Base
    storage :file
  end
 
  # model
 
  class Upload < Sequel::Model
    mount_uploader :file, MyUploader
  end
 
  # sinatra app
 
  get '/' do
    @uploads = Upload.all
    erb :index
  end
 
  post '/' do
    upload = Upload.new
    upload.file = params[:image]
    upload.save
    redirect to('/')
  end
 
  __END__
 
  @@ index
  <!DOCTYPE html>
  <html>
    <body>
      <form action="/" method="post" enctype="multipart/form-data"></div>
        <p><input type="file" name="image" /></p>
        <p><input type="submit" name="submit" value="Upload" /></p>
      </form>
      <% @uploads.each do |upload| %>
        <img src="<%= upload.file.url %>" />
      <% end %>
    </body>
  </html>

The app can be run like so:

  ruby example.rb

There’s a lot more I could have covered in this post, but my hope is that this brief illustration of the modularity, flexibility, and extensibility of CarrierWave will appeal to you as it did to me.

If you’re ready for more, check out:

I’m sure you’ll enjoy using CarrierWave as much as I have!

  • Erico

    @ trevorturk thanks for the write up. Do you think i can use Carrierwave with Eventmachine/Websocket for non-blocking upload and file streaming or will i need to patch anything in Carrierwave for that to work.

  • http://nepalonrails.com Millisami

    Or even with Resque to take off the thumbnail processing weight that might arise if it has to process 6-7 thumbnails?

  • http://www.80beans.com Thijs Cadier

    We’ve been using CarrierWave for a year or so now, very happy with it. Thanks for the great work!

  • Anonymous

    Hi Trevor, thanks for writing this up! A quick suggestion: specify which file the carrierwave configure block belongs in. A lot of new programmers won’t know you should put it in an initializer (if you’re using rails).

  • Anonymous

    Ich mag lesen Ihre Post Sir. Ich fühle, dass ich ein Sachverst?ndigen auf diesem Gebiet zu einem bestimmten Zeitpunkt zu werden. Vielen Dank für die mir die dringend ben?tigte Inspiration.
    Chanel Flap

    Dior taschen

  • http://www.linuxin.ro/2012/01/24-extremely-useful-ruby-gems-for-web-development/ 24 Extremely Useful Ruby Gems for Web Development | linuxin.ro

    [...] A Gentle Introduction to CarrierWave [...]

  • http://www.shadowtek.com.au/articles-resources/?p=989 24 Extremely Useful Ruby Gems for Web Development | Shadowtek | Hosting and Design Solutions

    [...] A Gentle Introduction to CarrierWave [...]

  • http://ios.codeinterior.com/24-extremely-useful-ruby-gems-for-web-development/ IOS world of development » 24 Extremely Useful Ruby Gems for Web Development

    [...] A Gentle Introduction to CarrierWave [...]

  • http://wpapp.phpfogapp.com/2012/01/24-extremely-useful-ruby-gems-for-web-development/ 24 Extremely Useful Ruby Gems for Web Development | WpApp Demo

    [...] A Gentle Introduction to CarrierWave [...]

  • http://www.interlacelab.com/blog/24-extremely-useful-ruby-gems-for-web-development/ 24 Extremely Useful Ruby Gems for Web Development – InterlaceLab

    [...] A Gentle Introduction to CarrierWave [...]

  • http://www.w3schools.eu/2012/02/24-extremely-useful-ruby-gems-for-web-development/ 24 Extremely Useful Ruby Gems for Web Development | W3schools.eu

    [...] A Gentle Introduction to CarrierWave [...]

  • http://webbytreats.com/tutorials/24-extremely-useful-ruby-gems-for-web-development/ 24 Extremely Useful Ruby Gems for Web Development « Webby Treats

    [...] A Gentle Introduction to CarrierWave [...]

  • Simar

    Thanks very much for share your story with us. Your work is phenomenal, wonderful
    http://www.songs.we.bs/

  • Jay

    Hi Trevor, thanks for your post.
    I’m new to Carrierwave and am trying out the Sinatra example you provided, running into a problem that I’ve yet to solve…

    After I upload a file, I’m getting this error:

    TypeError – can’t convert nil into String: /Users/jay/.rvm/gems/ruby-1.9.2-p290/gems/carrierwave-0.5.8/lib/carrierwave/uploader/url.rb:18:in `expand_path’Looking it over in irb, I’m finding that Uploads.all is returning nil and no matter how much I hack around I can’t seem to get back anything but nil from Uploads.all.Did something change in carrierwave since you posted your example?Thank you,/Jay