For Attaching Files, use Paperclip

Jon Yurek

Last Update: For archival reasons, I’m removing direct links to releases, etc. from here. All the info you need is at the official paperclip project page.

For some reason, file attachment is annoying. I don’t know why, and I know a lot of people have attempted to solve the problem in the past, myself included. Yet it still is. Having gotten fed up with gotchas and design decisions that we didn’t agree with, I went and wrote Paperclip on the plane to RailsConf last year. We’ve been using it here in various forms since and IMHO it’s the way to handle uploads, and finally decided that it should be released.

class User < ActiveRecord::Base
  has_attached_file :avatar,
                    :styles => { :square => ["64x64#", :png],
                                 :small  => "150x150>" }
end

A file is treated like any other attribute. It’s assigned like any other attribute, and it’s not saved until you call #save. It doesn’t have its own model. You can say where it’s saved on the filesystem, and what URL it’s referred to by (which means you can let Apache/nginx handle it or you can route it through the app for permissions/security). You can say what thumbnails are made, what resolution and format they are, and you can actually save cropped square thumbnails without any hassle.

class AddAvatarToUser < ActiveRecord::Migration
  def self.up
    add_column :users, :avatar_file_name, :string
    add_column :users, :avatar_content_type, :string
    add_column :users, :avatar_file_size, :integer
  end

  def self.down; ...; end
end

You don’t need mini_magick (which we’ve found may have been causing issues), you don’t need ImageScience (which, on the first image we tried to upload, failed to decode it, and it was a simple GIF), you don’t need RMagick (which has memory issues that were the impetus for mini_magick in the first place). You just need ImageMagick installed somewhere, which is as easy as yum, apt-get, or port on any system worth hosting on.

And this isn’t just for avatars and images. You can upload anything. No thumbnails are made by default, so it won’t automagically choke on your Excel docs.

Usage

In your model:

class User < ActiveRecord::Base
  has_attached_file :avatar,
                    :styles => { :medium => "300x300>",
                                 :thumb  => "100x100>" }
end

In your edit and new views:

<% form_for :user, :html => { :multipart => true } do |form| %>

<%= form.file_field :avatar %>
<% end %>

In your controller:

def create
  @user = User.create( params[:user] )
end

In your show view:

<%= image_tag @user.avatar.url %>
<%= image_tag @user.avatar.url(:medium) %>
<%= image_tag @user.avatar.url(:thumb) %>

Installation

piston import https://svn.thoughtbot.com/plugins/paperclip/trunk

It can’t be everything for everyone, but for the vast majority of cases we’ve come across, this is the right fit. Really, once you use this you’ll wonder why managing files was such a hassle.

Visit our Open Source page to learn more about our team’s contributions.