Jim Neath

Manchester based Ruby on Rails & Facebook App Developer

Paperclip is an awesome rails plugin by Jon Yurek at Thoughtbot. It is one of many plugins currently available that cater for file uploading and thumbnailing (see: Attachment_fu, file_column, etc). Now a quick quote from Jon:

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.

Installing Paperclip

You can install Paperclip using a variety of different methods:

svn export https://svn.thoughtbot.com/plugins/paperclip/tags/rel_2-0-2
piston import https://svn.thoughtbot.com/plugins/paperclip/trunk

You can also grab Paperclip from the git repository.

Quick Note: If you’re a windows user, you’re going to need to go for the trunk version as this contains a fix to a problem that basically meant that Paperclip borked.

Basic Usage

class User < ActiveRecord::Base
  # Paperclip
  has_attached_file :photo,
    :styles => {
      :thumb=> "100x100#",
      :small  => "150x150>" }
end

Attached files don’t need to have a separate model (thank god). Your attachments are treated just like any other attribute. Images aren’t saved until your model is saved. There are a lot of bonus options but I’ll cover them towards the end of the article.

class AddPhotoToUser < ActiveRecord::Migration
  def self.up
    add_column :users, :photo_file_name, :string # Original filename
    add_column :users, :photo_content_type, :string # Mime type
    add_column :users, :photo_file_size, :integer # File size in bytes
  end

  def self.down
    remove_column :users, :photo_file_name
    remove_column :users, :photo_content_type
    remove_column :users, :photo_file_size
  end
end

Don’t forget to add these columns! Otherwise you’ll end up scratching your head and wondering where the hell you went wrong. The first part of the column names is the same as whatever you’re called your attached file. In our case that’s photo. Now update your database:

rake db:migrate

Now that your database is sorted, we can start working on adding some content. In your view you can add a file field like you would normally:

<% form_for :user, :html => { :multipart => true } do |f| %>
  <%= f.file_field :photo%>
<% end %>

Don’t forget the :multipart => true part or everything will fail. Then you will cry.

Now in your controller, you don’t need to do a thing (hooray).

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

You should now be able to upload user photos to your hearts content.

To display your user’s photos all you need to do is call:

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

The first call will display the original image. The second one will display the thumbnail image. Easy, yes?

Paperclip Validations

At the moment Paperclip has two different validation types, validates_attachment_presence and validates_attachment_content_type.

validates_attachment_presence

validates_attachment_presence gives your ActiveRecord style validations to check to see if your paperclip model has an attachment present.

validates_attachment_presence :avatar

validates_attachment_content_type

validates_attachment_content_type lets your check the type of file that has been uploaded by checking it’s mime type.

validates_attachment_content_type :avatar, :content_type => 'image/jpeg'

Paperclip Options

Now that you’ve seen how easy to use and awesome Paperclip is, let’s have a look at some of the additional settings you can use:

has_attached_file :photo, :url => "/:class/:attachment/:id/:style_:basename.:extension"

Using :url you set when your images can be accessed from. The above setting would mean that your files are located at URLs similiar to /user/photo/1/thumb_originalfilename.jpg

has_attached_file :photo, :default_url => "/:class/:attachment/missing_:style.png"

The :default_url option is used if there is no attached file for a model. If a user doesn’t have any uploaded avatar you could use this option to set a default avatar to show.

has_attached_file :photo, :styles => { :normal => "100x100#", :small => ["70x70>", :jpg] }

:styles is a hash of thumbnail styles. The styles use the standard ImageMagick geometry rules. Paperclip also adds the ’#’ option which will create square thumbnails that are nicely cropped.

has_attached_file :photo, :default_style => :thumb

:default_style is pretty straight forward. You can select a default style from your style list that will be called, instead of the original file, when you use @user.photo.url

has_attached_file :photo, :path => ":rails_root/public/:class/:attachment/:id/:style_:basename.:extension"

Using :path you can select where the files are saved to on your box. If you change this, make sure to change the :url setting to relate to the new path.

has_attached_file :photo, :whiny_thumbnails => true

:whiny_thumbnails will raise an error if there is a problem creating thumbnails. Set to true by default.

Some Waffle

Paperclip is a great plugin. It has a smaller memory footprint than Attachment_fu, it doesn’t require the use of Rmagick (eugh) and it has all the options that I’ve wished that Attachment_fu had. Give it a try and let me know what you think

Again, maximum kudos to Jon Yurek and all the guys over at ThoughtBot.

blog comments powered by Disqus

I am available for freelance work! Click here to email me.

Jim Neath is a Freelance Ruby on Rails & Facebook app developer from Manchester, UK, currently working for Engine Yard.