A Gentle Introduction to CarrierWave
Note: 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>
<input type="file" name="image" />
<input type="submit" name="submit" value="Upload" />
</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:
- the readme
- the wiki
- the Mocking fog when using it with CarrierWave post from Mike Gehard
- and the How to set up CarrierWave for local storage with AppCloud documentation for Engine Yard AppCloud users.
I’m sure you’ll enjoy using CarrierWave as much as I have!
Share your thoughts with @engineyard on Twitter