Edit/Update Paperclip Plugin Attachments

Friday
Aug 29, 2008
12:37 AM

So I’ve discovered the wonderfully easy-to-use Paperclip attachment plugin for Ruby on Rails, written by Jon Yurek at Thoughbot .

I like that attachments are treated like any other class instance attribute (@post.image), instead of having to be associated with a post from a separate assets resource entirely. It uses Imagemagick, it has a small footprint, many of the features that make attachment_fu great, and others that it lacks.

When I started playing around with Paperclip, I noticed that there are some RESTful actions missing in the documentation: destroy, edit, update, and so on. That same documention intimates that you should/can have an upload form on your edit page, so I persevered – it would really be ideal if users could simply upload new images and documents, overwriting existing ones.

When I got to this point, I did what anyone would do: wrote out the actions based on the generated scaffolding patterns, hoping it would ‘just work’. I had a post model with attachments for an image and also a sample text. Not only do I want users to be able to swap these out, but to update other columns in the class instance without losing the existing files attached to the record.

When I went ahead a tested the configuration I’d cobbled together, it wasn’t working correctly. It didn’t update, it created a new record, with the existing values, which was…not ideal.

Evaluating the form_for tag, I noticed that the tag I’d copied in from the RiDocs was using was a little unusual:

<% form_for :post, @post, :url => posts_path, :html => { :multipart => true } do |f| %>

The tutorials online only require the symbol for the class and the multipart => true bits. Not only that, but knowing how RESTful conventions work, that :url => posts_path is an obvious problem: when you’re working with a class instance, your paths should be singular.

Changing it to singular (:url => post_path) didn’t work – suddenly I was getting an error stating that the ID of the object wasn’t an action! Well, obviously. So I needed to explicitly state the action:

<% form_for :post, @post, :url => post_path, :action => 'update', :html => { :multipart => true} do |f| %>  

But this didn’t work either! The update parameter was either being overlooked or wasn’t providing the correct parameters in the expected format. Finally, researching the available parameters for the form_for tag, I came up with this:

<% form_for :post, @post, :url => post_path, :html => { :multipart => true, :method => :put } do |f| %>  

Which explicitly states the http method used in the transaction. This works beautifully! File attachments remain the same unless you’ve selected new ones, it works for multiple simultaneous attachments on a model…it’s gorgeous. I hope this helps, I couldn’t find much info on edit/update features for Paperclip.