Multiple File Uploads With Paperclip (Screencast)

Multiple Attachments with Paperclip

Paperclip is a really great gem/plugin for Ruby on Rails that makes handling file attachments super easy. If your new to paperclip I would highly recommend taking a look at the following resources before getting started:

While Paperclip is great when working on projects that require only one file attachment, things can get a little tricky when you need to work with multiple files. This makes something that should be easy, say, a Photo Album that has_many attachments hard to setup if you've never done it before.


Setup and Configuration

# config/environment.rb
gem.config "paperclip"

# Install the Gem
rake gems:install

# Generate the "Asset" Model
ruby script/generate model Asset article_id:integer

# Add the required Paperclip columns to our Asset model
ruby script/generate migration AddPaperclipToAssets image_file_name:string image_content_type:string image_file_size:integer

# Tell Paperclip where to find your ImageMagick installation (not always required)
# development.rb
Paperclip.options[:image_magick_path] = '/path/to/your/image_magick'


Setup the Models

 # app/models/asset.rb
belongs_to :article
has_attached_file :image,
    :styles => {
      :thumb=> "100x100#",
      :small  => "300x300>",
      :large => "600x600>"
        }
        
# app/models/article.rb
has_many :assets, :dependent => :destroy
accepts_nested_attributes_for :assets, allow destroy => true

Setup the Controllers

# apps/controllers/articles_controller.rb
def new
        @article = Article.new()
        5.times { @article.assets.build }
end

def edit
        @article = Article.find(params[:id])
        5.times { @article.assets.build }
end

Setup the Form Partial

# apps/views/articles/_form.html.erb
# Make sure your form is multipart with :html => { :multipart => true }
<div class="newPaperclipFiles">

        <%= f.fields_for :assets do |asset| %>
        
           <% if asset.object.new_record? %>
                 <%= asset.file_field :image %>
           <% end %>

       <% end %>

</div>

<div class="existingPaperclipFiles">
        
     <% f.fields_for :assets do |asset| %>
        
          <% unless asset.object.new_record? %>
        
                <div class="thumbnail">
                        <%= link_to( image_tag(asset.object.image.url(:thumb)), asset.object.image.url(:original) ) %>
                        <%= asset.check_box :_delete %>
                </div>
                
          <% end %>        
        
     <% end %>
</div>

  1. 2dccc7c8fa86c0600b335c94dc3122e4

    Gregg Turnbull

    9:13 PM on Friday, August 13th, 2010

    Just a few updates needed to make it work on my end:

    in _form.html.erb added to form tag ", :html => { :multipart => true }"
    { :multipart => true } do |f| %>

    and in # app/models/asset.rb added ",allow destroy=>true"
    accepts_nested_attributes_for :recharge_assets, :allow_destroy => true

    After that all worked dandy... thanks for the post.

  2. 4a24c05eeb9e3ae07ac3a63b5fafa9da

    Emerson Lackey

    5:04 PM on Monday, August 16th, 2010

    Thanks Gregg,
    Added the relevant changes to the post.

  3. D4534a68fa60c06a3bc8dad302140fbd

    Allen

    8:41 AM on Thursday, August 19th, 2010

    Thinking about if asset model is polymorphic, how could it be? or asset model belongs_to user model, where should we add user association

  4. 976a7b3a7d9c1a0396c33f77e3b22e6f

    oscar

    9:14 AM on Friday, August 27th, 2010

    Thanks for the sreencast!

    Please, can you attach the rails project?
    It would be fantastic to see the video, look the code and do some experiments.

  5. A83adb7b4099892a8f714cbb1aaa928a

    mulox

    3:39 PM on Friday, August 27th, 2010

    Very good screencast! i just see it and it's very useful.

    Please, do another screencast teaching how to add javascript to delete the images, or the button to add an image field dynamically.
    (any hope to see the code or your blog?)

    Thanks

  6. 4d98f8e74ec9d084cda74b118af440ae

    gerard

    8:34 AM on Monday, August 30th, 2010

    Thanks for the screencast, it's very useful.
    Can you do another explaining how to do last steps of the screencasts? all the stuff with ajax...
    Is released the code of your blog? i'm interested in how you resolve the problem of create dynamically all the attachments that you want...

  7. F67bc7a578e77c826b2a4876163eff09

    Pierre-Alain Bandinelli

    10:12 AM on Sunday, September 26th, 2010

    Hello Emerson,
    Very good post. But a few things to change for Rails 3 :

    In # config/environment.rb
    gem.config "paperclip" must become
    gem "paperclip"

    To install the Gem
    rake gems:install must become
    bundle install

    In the view _form.html.erb,
    must become

    In the model article.rb,
    accepts_nested_attributes_for :assets, allow destroy => true
    must become
    accepts_nested_attributes_for :assets, :allow_destroy => true

    I hope it will help !
    Thanks again for the post

  8. F67bc7a578e77c826b2a4876163eff09

    Pierre-Alain Bandinelli

    10:14 AM on Sunday, September 26th, 2010

    Obviously sthg went wrong with my previous post :

    In the view _form.html.erb, the :_delete must be replaced with :_destroy
    "" must become ""

  9. F67bc7a578e77c826b2a4876163eff09

    Pierre-Alain Bandinelli

    10:15 AM on Sunday, September 26th, 2010

    Once again sorry, I've just understood that the posts do not allow ruby code starting with <%
    So
    asset.check_box :_delete
    must become
    asset.check_box :_destroy

  10. 069bba46818ee29f258abb24923884bd

    Stan

    8:44 AM on Tuesday, October 5th, 2010

    Thanks a lot for the podcast! Exactly what I was looking for.

  11. 0e4d3598d35e852948b24f136d08274b

    Matenia Rossides

    2:10 PM on Monday, November 1st, 2010

    Hi, Fantastic Screen Cast,

    I have implemented this many times over to date, and still love the approach.

    I have one query that is completely doing my head in at the moment.

    I want to render the existing thumbnails on the edit page but need to order them by their position attribute. Is there a way to do fields_for and sort by position not id?
    Hope there's someone out there that has had this problem and has a workaround / solution :)

    Kind Regards,
    Matenia

  12. 67a9032d90886223a370783bdcdad5c6

    Susi

    2:12 PM on Tuesday, November 9th, 2010

    This works under rails 3.0 too! Great work.

    How do you display uploaded images? Can you put this in your tut? That would make your tut perfect. Many people would be glad. Thanks

  13. 00ec7a7094f48216e092bc956ebac041

    John

    5:48 PM on Tuesday, December 7th, 2010

    Thanks for the tutorial. I just set this up with Rails 3 and it worked great.

  14. 2969ae921531acf2eea96b395f37705d

    Mikael Jansson

    12:37 PM on Monday, December 20th, 2010

    asset.check_box :_delete
    What if I want that to be a link under the thumb that says Destroy or Remove or something.

  15. 2969ae921531acf2eea96b395f37705d

    Mikael Jansson

    10:48 AM on Tuesday, December 21st, 2010

    "asset.check_box :_delete
    What if I want that to be a link under the thumb that says Destroy or Remove or something."

    Figured it out.

  16. Bcd1449d0ae15d131c4f7b1a7371de10

    Stephan van Eijkelenburg

    6:46 PM on Thursday, December 23rd, 2010

    Thanks for the article, helped me a lot.

    I think I might have found a solution to the 'now knowing how many files you want to attach upfront' problem mentioned at the end of the screencast.

    Instead of using 'fields_for' you could use:
    true %>

    This way you can upload many photos in modern browsers. For older / crappy browsers it's possible to insert " true %>" multiple times. Adding them with JQuery is also an option.

    This worked for me in rails 3, not tested it in older versions

    I hope this helps someone :)

  17. Bcd1449d0ae15d131c4f7b1a7371de10

    Stephan van Eijkelenburg

    3:33 AM on Friday, December 24th, 2010

    Whoops, I see that my code got escaped / not displayed, sorry. Next try:

    Instead of using 'fields_for' you could use:
    file_field_tag 'article[assets_attributes][][image]', :multiple => true

    This way you can upload many photos in modern browsers. For older / crappy browsers it's possible to insert "file_field_tag 'article[assets_attributes][][image]', :multiple => true" multiple times. Adding them with JQuery is also an option.

    This worked for me in rails 3, not tested it in older versions

    I hope this helps someone :)

  18. D8ba4a7aaf48b9ad485f551b3a3f9301

    Raymond

    10:14 PM on Tuesday, January 11th, 2011

    Hey. Great tutorial.

    I'm wanting to limit the amount of upload fields in the Edit view based on how many assets there already are in an article, so that an article will never under any circumstance end up with more than 5 assets.

    So in the Edit action of the Articles controller I changed:

    5.times { @article.assets.build }

    to

    (5 - @article.assets.length).times { @article.assets.build }

    And I seem to get the right amount of upload fields based on how many assets already exist, but my question is, is this the best way to accomplish this? Bulletproof way of assuring there's never more than 5 assets per article and all?

    Thanks for any response.

  19. 1b35d18aed766e9f2908a4059c642974

    mike

    11:33 AM on Wednesday, January 26th, 2011

    Hello,

    Would the source code for this screencast happen to be available somewhere for download?

  20. F175acd4403fd78c0ba6820509238ebc

    Frank Thomas

    8:11 AM on Thursday, February 3rd, 2011

    Hi, I'm getting "ActionDispatch::Http::UploadedFile" inside my photos_attributes params. Anyone, know why this would happen? Thanks for the help!

  21. F921fa5d507b31ef6984fd3d77ae710c

    modocache

    9:01 AM on Saturday, February 5th, 2011

    thanks a lot, this was really helpful. got it working on ror 3.0.3 / paperclip 2.3.8 with only minor adjustments:

    articles_path, :html => { :multipart => true } ) do |f| %>

    awesome resource, thanks.

  22. 8c4a58ab13db084eb026a2f664548841

    Norm

    4:49 AM on Monday, February 7th, 2011

    Thanks for this!
    I'm new to rails and this really helped with a project I'm working on.

  23. Bc69e81cc4794c23cbb74c60d3ba93a4

    Alir3z4

    1:54 AM on Friday, February 25th, 2011

    tnx a ton!
    i like carrierWave.
    and i try this with carrierwave instead paperclip.

  24. 8307b58b6f3c7a9d98e64f828341f881

    Uriel

    6:39 PM on Wednesday, March 2nd, 2011

    What if i'm trying to upload multiple files to different models? How can I do the polymorphic association?

  25. 7fdbce5f694af64e309fc8482ec8027f

    Mike

    4:01 PM on Wednesday, April 13th, 2011

    I've a name attribute and added the attr_accessible to it in the app/models/article.rb file:
    attr_accessible :name

    After that it didn't allow me to save the images. Using rails 3.0.5. Anyone encountered this?

  26. B59f247d0c51158dfe9111159d07cbd4

    Wijnand

    11:08 AM on Wednesday, April 27th, 2011

    Awesome... works perfectly.
    Thanks for sharing : )

  27. 4658bdf82bd804e1a52256927683b583

    Bob

    10:09 AM on Thursday, October 13th, 2011

    And how can I upload unlimited files per one upload?

  28. 7663abdf5f386a3b676ddedc9347bbd3

    iotriado

    10:31 PM on Sunday, December 18th, 2011

    i use rails 3.0.11. When i try to save a new object with a nested paperclip photo at first it is not saved (obj.save = false). When i saved it without select a photo the object is created and stored to the database as well. when i edit the object and add a photo to it the object is saved successfully and the photo is upload too. Did anyone knows whats going on?

  29. Bd48dcdbeee46e9be3dedae5500dde68

    Lev

    11:58 AM on Wednesday, December 28th, 2011

    Maybe smb have already commented it, but anyway:
    Here is some useful moments (tested on ruby 1.9.3, rails 3.1.3):
    1. you should have installed ImageMagick
    2. in article view in '' write '' instead of ''. Or you won't see the form with uploaded images.
    3. in Article model add attr_accessible :assets_attributes . This will help you to done with some warnings.

  30. Bd0c938eea2b3c07aa2c567a0d4e8407

    Frank

    3:53 AM on Friday, January 6th, 2012

    how would you display the images in the show view?

  31. B26601b27ce83ae065b09046282a78a4

    Jorge Giraldo

    5:51 PM on Thursday, January 19th, 2012

    Thanks, this is a great post. However, what if you don't know how many images you're going to upload? I mean, can the controller have a variable that depends on the images you want to upload, so that you don't need to have a fixed number of them?

  32. 161cfa234780988a5269603abda9070c

    Kleber

    9:23 PM on Tuesday, February 28th, 2012

    Thanks for posting this article! Very helpful !

    In this case how do you test using Rspec?

  33. 1f4261df67cc64611355a3eb55e1d120

    Fernando

    11:11 AM on Tuesday, April 24th, 2012

    Congratz for the excelent screencast.
    I followed all steps, but I'm still getting the error

    Can't mass-assign protected attributes: asset

    Even with the attr_accessible :content, :title, :assets_attributes on post.rb model

    I'm using paperclip 3.0.2, rails 3.2.3 and ruby 1.9.3. Maybe something changed in paperclip/rails after this screencast was recorded.

  34. F80c5168b92fe9d49b0668cde3bdd57c

    gordon

    3:43 PM on Sunday, May 6th, 2012

    i think this was article was last updated in 2010 before rails 3.
    May be a good idea to put a disclaimer at the top.

  35. 62ca020e7f2e29730a62ee6585781766

    Britt

    4:26 PM on Friday, May 11th, 2012

    Said before, but important. You must add:

    # in the 'article.rb' model
    attr_accessible :assets_attributes

    this will silently fail and drive you nuts if you forget that

  36. A234690c5cd8555d0a0743b166a63497

    Crhistian

    12:14 AM on Thursday, October 11th, 2012

    how I can display the images on show?

    I would appreciate your support, thanks

  37. 6e959a2e4c6f437404bd0669c7f34a9b

    Lakeisha

    8:32 AM on Thursday, December 20th, 2012

    My brother suggested I would possibly like this blog.
    He was once entirely right. This put up actually made my day.
    You can not consider just how a lot time I had spent for
    this info! Thanks!

  38. 261b09a264b681397dc07fb91384dd04

    Kumar

    9:08 AM on Thursday, December 27th, 2012

    In case we are parsing data from the file which we are uploading (multiple files too) and filling up rows in the database. In that case each Article model (if I carry on with your example) should have multiple entries from the individual asset file and therefore we need to provide asset ID to the Article model. So...
    Is it also possible to have a reverse association in contrast to what you have explained in the screencast i.e. asset would have "has_many :articles" and Article "belongs_to :asset"????? Will paperclip work fine in this case???