Paperclip: Attaching Files in Rails

April 17th, 2008

Edit: Added paperclip validations

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 seperare model (thank god). Your attachments are treated just like any other atribute. 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.

(Possibly) Related Posts

You can follow any responses to this entry through the RSS 2.0 feed. Trackback from your own site.

37 Responses to “Paperclip: Attaching Files in Rails”

  1. April 17th, 2008 at 4:32 pm - Harold Says:

    Hi!

    Nice work, this really takes the hassle of attachment_fu. Also I was wondering if PaperClips would work with ImageScience?

    Thanks!


  2. April 17th, 2008 at 5:47 pm - Roob Says:

    this is AWESOME! been searching for this quite awhile, especially because attachment_fu needs extra models for attachments. will try this asap.


  3. April 17th, 2008 at 5:52 pm - Jon Yurek Says:

    Thanks for the good overview! I’m glad you like it.

    I should point out, though, that “:filename” isn’t valid inside of the path and url options anymore. It should be “:basename.:extension”. Also, the project is on git now for all so inclined.


  4. April 18th, 2008 at 1:41 am - links for 2008-04-18 « Mike Does Tech Says:

    [...] Paperclip: Attaching Files in Rails | Jim Neath (tags: rubyonrails upload plugin) [...]


  5. April 18th, 2008 at 10:11 am - admin Says:

    @Harold: To quote Jon: “You just need ImageMagick installed somewhere”.

    @Jon: I totally forgot about :filename not being used. I was just going through paperclip.rb to look at the options but :filename still appears in there.

    I’ve updated the post to use “:basename.:extension” now, and added the git repos.


  6. April 18th, 2008 at 2:28 pm - Ed Spencer Says:

    Looks great, will plug this in on the next project for sure (not that attachment_fu is particularly horrible or anything). Good to keep finding fellow UK Rails people too, we just seem to keep popping up :)


  7. April 19th, 2008 at 5:23 am - Kamran Says:

    Does this have a smaller memory footprint than attachment_fu+ImageScience, or attachment_fu+ImageMagick? Just wondering cause i just got through setting up all of that (with ImageScience), and i don’t really see much here that is different other than not needing an extra model for the images, which i kinda like anyhow. It would be cool to add some other effects because you are using imagemagick, maybe some stuff like annotation, round corners, drop-shadows or grayscale and sepia.


  8. April 19th, 2008 at 9:32 pm - links for 2008-04-19 Says:

    [...] Paperclip: Attaching Files in Rails | Jim Neath 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 (tags: file rails uploads) [...]


  9. April 21st, 2008 at 9:20 am - This Week in Ruby (April 21, 2008) | Zen and the Art of Programming Says:

    [...] week two must-read, hands-on posts were published: Import Gmail Contacts using Ruby on Rails and Paperclip: Attaching Files in Rails. Both cover tasks that are extremely common and useful for many web [...]


  10. April 24th, 2008 at 6:40 pm - Asis Hallab Says:

    Good day!

    I really dig Paper-Clip.
    I just have one question: Is there an option liek “has_many_attached_files”, to assign many attachments to any ActiveRecord..

    Many tanks in advance!


  11. April 24th, 2008 at 8:14 pm - Jim Neath Says:

    @Kamran: I’m not entirely sure about the footprint comparisons using attachment_fu with an different image processor than ImageMagick. It would be interesting to see though

    @Asis Hallab: There’s not an option to attach many files. Well, you can attach different files. You could have has_attached_file :photo and has_attached_file :doc or something, but I assume you mean attaching multiple instances of the same file type?


  12. April 25th, 2008 at 9:09 am - Asis Hallab Says:

    Dear Jim,

    yes, attaching multiple instances of the same file type is just what I want to do.
    Well, I’ll try creating a wrapper like ‘Attachment-Holder’ and assign multiple instances of that wrapper. It’s not truly the crown of coding, but it solves my problem for now. Don’t you think?


  13. April 25th, 2008 at 12:00 pm - Building a Social Network Site in Rails | Jim Neath Says:

    [...] Paperclip is a brilliant plugin by Jon Yurek over at ThoughtBot. Paperclip is used for managing file uploads and attaching the files to models. You can read more over at my article: Paperclip: Attaching Files in Rails. [...]


  14. April 26th, 2008 at 8:09 pm - Ben Says:

    I am having a hard time finding a real world usage for this other than your ‘avatar’ examples. More common that wanting an avatar for a user profile is the ability to attach images to a blog post for example. Being that I couldn’t have more than one image per post - it makes the whole thing pretty useless. Correct me if I am wrong (and I hope I am.) But this just seems to me like a glorified way to add images to a user profile.


  15. April 27th, 2008 at 3:24 pm - Ben Says:

    Ignore my comment above, I didn’t really think that through all the way. I think what I will do is create an Attachment or Bucket Model, attach things to this model and create some special syntax to be able to link or embed them in posts.


  16. April 29th, 2008 at 7:32 pm - Randy Says:

    Is there a way to incorporate this with acts_as_commentable?

    I added has_attached_file to the comment.rb in the vendor/plugins dir and followed directions but its not saving the file. It keeps coming up blank.


  17. May 2nd, 2008 at 6:08 am - tripurari Says:

    How to store the original file name,type of file and size of file in the databse using paperclip

    plz is there any one then help me


  18. May 9th, 2008 at 1:44 am - Marco Borromeo // blog » Blog Archive » links for 2008-05-09 Says:

    [...] Paperclip: Attaching Files in Rails | Jim Neath 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). (tags: activerecord development file forms image photo plugin plugins programming rails ror ruby rubyonrails tutorial tutorials upload paperclip) [...]


  19. May 14th, 2008 at 11:40 am - Jeff Says:

    When I also use validate_attachment_presence, paperclip saves null into the database. this seems to be a bug.


  20. May 14th, 2008 at 7:58 pm - Dominik Weiss Says:

    Paperclip is awesome! Thanks for this little introdution :-)

    Anyway, I just wanted to add how to validate the content_type of the the upload:

    app/models/user.rb:
    validates_attachment_content_type(:image, { :content_type => ['image/jpg', 'image/jpeg', 'image/gif', 'image/png'] })
    validates_attachment_presence(:image)


  21. May 15th, 2008 at 1:49 pm - SWFUpload, Paperclip and Ruby on Rails | Javascript Says:

    [...] that takes care of all the grunt work and lets you get on with other stuff. I’ve covered how to use Paperclip [...]


  22. May 16th, 2008 at 7:47 am - John Shamstonge Says:

    Hey there,

    Does anyonek now if Paperclip is OK to use for non-image files?


  23. May 16th, 2008 at 10:34 am - Jim Neath Says:

    @tripurari - If you run the migrations shown above then Paperclip should automatically add those details to your database

    @Jeff - Not had that problem myself. Try reporting to the guy sat Thoughtbot.

    @Dominik Weiss - I don’t think the validations were present when I originally wrote this. Noticed them myself today, so I’ve updated the article. Thanks for the heads up.

    @John Shamstonge - Paperclip is okay to use with any kind of file you want to attach to a model. Make sure you validate the file with validates_attachment_content_type though.


  24. May 22nd, 2008 at 4:15 am - Dios Says:

    How do I change the DPI setting. I want it at 72 dpi, but it seems to default to 350 dpi for jpeg. Any way to control size/quality?


  25. May 27th, 2008 at 3:31 pm - Kabish Says:

    Looks fantastic, it’s just a pity that it allows only one instance per file type… loses some usefulness that way.

    Good work!


  26. May 29th, 2008 at 5:22 pm - RubyPimp Says:

    I love you!!!!!!


  27. May 31st, 2008 at 10:18 am - t3i Says:

    Hi, i’m wondering what happens when records are updated. It seems to be setting all the attributes to NULL, is there a way to make it not change the photo attributes unless something is posted?


  28. June 4th, 2008 at 1:08 am - Jonas Nicklas Says:

    Good work, it looks pretty solid :) Though of course, as the author of a file uploading plugin myself (http://uploadcolumn.rubyforge.org), I have to wonder why you looked at file_column (which hasn’t been maintained for years) and if you had a look at UploadColumn at all? UC and Paperclip seem very similar to me, so I’m wondering if there were any issues you had that made you decide to write your own plugin, so that those could possibly be fixed.


  29. June 4th, 2008 at 9:19 am - Jim Neath Says:

    Hi Jonas,

    I didn’t actually write the Paperclip plugin, although I am an avid user. It was written by Jon Yurek from Thoughtbot.

    When I first started using Rails, I used to use file_column but I stopped using it for some reason I can’t remember. I’ve not had a look at upload column yet, but will look into it.

    - Jim


  30. June 4th, 2008 at 9:47 am - Converting Videos with Rails: Converting the Video | Ruby on Rails Says:

    [...] videos onto our server. Details of how to install paperclip can be found in my previous article: Paperclip: Attaching Files in Rails. To install you can use any of the [...]


  31. June 6th, 2008 at 8:14 pm - Chris Says:

    thanks for your article, this has helped a lot.

    but i have one question:
    would it be possible to provide paperclip just with a url to an image and it will download and store the picture in my filesystem?


  32. June 18th, 2008 at 11:46 pm - Sam Says:

    Nice writeup. One of my favourite parts is “Don’t forget the :multipart => true part or everything will fail. Then you will cry.” ;)


  33. June 19th, 2008 at 4:12 am - Avishai Says:

    Wow, this is great, thanks :-)

    Just want to let people know about one gotcha that I found while trying to get avatars uploaded with my User model.

    Especially if you’re using a plugin like restful_authentication, you have make sure that the avatar attribute is allowed to be mass-assigned:
    attr_accessible :avatar #or whatever your calling the attachment
    otherwise it won’t allow you do update it via mass-assignment.


  34. June 19th, 2008 at 1:59 pm - Arik Jones Says:

    I can see this plugin blowing attachment_fu out of the water!


  35. June 21st, 2008 at 2:20 pm - David C Says:

    Re: Attaching several images
    Do with seperate model

    AttachemntModel
    has_attached_file :photo, :styles => { :thumb=> “100×100#”, :small => “150×150>” }
    belongs_to: post

    PostModel
    has_many: attachments


  36. June 25th, 2008 at 6:04 pm - johnny Says:

    Just wanted to say that paperclip is awesome! I just used it to upload pdfs. Worked fine. Thanks for the pointers Jim!


  37. July 4th, 2008 at 5:54 am - regenerate paperclip thumbnails — code to customer — ruby on rails web developers from new zealand Says:

    [...] a good tutorial on Jim Neath’s [...]


Leave a Reply

Jim Neath is a 23 year old Ruby on Rails developer from Manchester, UK. Contact Jim Neath

Recommend Me

Categories

Stalk Me