has_many file attachments using Paperclip 16 Jun 2010
Tags: gem, paperclip, has_many, multiple file attachments

I decided to use paperclip instead of attachment_fu for our new app. This is just a procedure on how to use paperclip with a has_many association.

We create two models: post and post_photo

plain
>> ruby script/generate model post title:text body:text
>> ruby script/generate model post_photo post_id:integer

and associate them as follows.

ruby
class Post < ActiveRecord::Base
  has_many :post_photos
end

class PostPhoto < ActiveRecord::Base
  belongs_to :post
  has_atttached_file :photo
end

Using paperclip's generator we create a migration to add columns to post_photo

plain
>> ruby script/generate paperclip post_photo photo

After that, create your views and controller methods. (Btw, I use haml for the views. I also like creating an associated record using virtual attributes. I also used the prototype based js, Builder, to create dom elements.)

haml
# Post#new.html.haml
- form_for @post do |f|
  %label Title
  = f.text_field :post

  %label Body
  = f.text_area :body

  %label Photos
  = file_field_tag 'post[photo_attributes][]'

  #new_photos
  = link_to_function 'Add', 'add_file_field()'

:javascript
  function add_file_field() {
    var div = Builder.new('div');
    var file = Builder.new('input', {type:'file', name:'post[photo_attributes][]'});
    var link = Builder.new('a', {onclick:'$("this").up().remove();}, 'Remove');

    $('div').appendChild(file);
    $('div').appendChild(link);
    $('new_photos').appendChild(div);
ruby
# PostsController
def create
  @post = Post.new(params[:post])

  if @post.save
    flash[:notice] = 'Post saved'
    redirect_to @post
  else
    render :action => :new
  end
end

# post.rb
def photo_attributes=(attribs)
  attribs.each do |attrib|
    post_photos.build :photo => attrib
  end
end