iprog.com

uploading multiple files with attachment_fu

i was recently sharing with someone how to make multiple uploads work with the attachment_fu plugin. as an aside, attachment_fu is the successor to acts_as_attachment. if you were planning to use acts_as_attachment, upgrade your plans and use attachment_fu instead.

multiple file uploads are actually fairly straight forward.

first, in the view:

1<%= file_field_tag 'attachment_data[]' %>

put as many of these in the view as desired. it’s also easy to cause an arbitrary number of them to be added via javascript by the user’s browser.

then, in the controller:

1@attachment = Attachment.new
2params[:attachment_data] ||= []
3params[:attachment_data].each do |file|
4  @attachment = Attachment.create({:uploaded_data => file}) unless file == ""
5end

Attachment is my model for uploaded file—substitute as appropriate. as this isn’t a complete how-to for attachment_fu, i won’t get into configuring attachment_fu or the model here.

that’s it. that wasn’t so painful, eh?

tags: attachment_fu, plugins, ruby, rails

by fabian

thanks,
but,
what do you put on the show.html.erb?

im lost there
thanks

by tm

just this:

<%= file_field_tag 'attachment_data[]' %>

if you want to allow three uploads, put it in there three times. you could even use ajax to allow the user to add it an arbitrary number of times.

the trick lies in the “[]” at the end of “attachment_data[]” which causes the upload data to be submitted as an array of files. the underlying code handles that array, whether it has one file in it or ten.

by Lee

so how exactly have you done this? I’m guessing you have an attachments table of some kind? if so could you give me some idea of how the table should look?

by tm

yes, as i noted in the article above, “Attachment is my model for uploaded file.” it just needs to be a standard attachment_fu compatible model. maybe something like this (untested):

1create_table "attachments" do |t| 2 t.integer 'parent_id' 3 t.string 'content_type' 4 t.string 'filename' 5 t.string 'thumbnail' 6 t.integer 'size' 7end

obviously it will probably need some kind of relationship to other data in your app.

by Shih-gian Lee

Thank you, sir! This is a life saver!

by Shih-gian Lee

By the way, what does @attachment.create({…}) do?

Thanks!

by Shih-gian Lee

Sorry, typo. It should be Attachment.create({…}).

by Shih-gian Lee

Sorry for the spam message. I found the answer here – http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M002214.

Thanks again for the great work!

by Pedro consuegra

i`ve been loking for this tutorial thanks!!!!!

but i have some problem when i upload my pics becouse there is no error but my app never upload the pics
this is my model maybe it have some wrong

class Image < ActiveRecord::Base

belongs_to :record, :polymorphic => true
has_attachment :content_type => :image,
:storage => :file_system,
:path_prefix => ‘public/records’
validates_as_attachment

end

Please help me!!!!!

by tm

Well, it’s hard to tell for sure what your problem might be. But, from looking at your Image class, Imageable module, and view, there are a couple things that jump out at me. Perhaps one of these will help guide you to a solution.

First, your module is set up to only process a single image (has_one :image). Yet your view supports multiple files.

Second, your module’s uploaded_data= method suggests that you’re trying to cause uploaded_data to be a virtual attribute on a model. That’s a nice idea. However, your form is going to pass the file upload data as only attachment_data[], not inmueble[attachment_data][] which is probably what your controller is expecting. I’m not sure on this though as I haven’t seen your controller.

You may find it helpful to look at your development.log. Specifically, look at the incoming parameters for the POST request from your form submission. See if everything is coming in as you are expecting.

Hope that gets you on the path to getting this working.

—t

by Pedro consuegra

and this module is my lib/imageable.rb

module Imageable
def self.included(base)
base.class_eval do
has_one :image, :dependent => :destroy, :as => :record
end
end
def uploaded_data=(data)
unless data.blank?
image.destroy if image
self.reload
create_image :uploaded_data => data
end
end
end

by Pedro consuegra

sorry, now it`s look better
module Imageable

def self.included(base)
base.class_eval do
has_one :image, :dependent => :destroy, :as => :record
end
end

def uploaded_data=(data)
unless data.blank?
image.destroy if image
self.reload
create_image :uploaded_data => data
end
end
end

by Pedro consuegra

and there is my view

<h1>Editing inmueble</h1>

<% form_for @inmueble, :html => {:multipart => true} do |f| >
<
= f.error_messages %>

<p> <%= f.label :tipo %><br /> <%= f.text_field :tipo %> </p> <p> <%= f.label :descripcion %><br /> <%= f.text_area :descripcion %> </p> <p>

<b>Image</b><br /> <%= file_field_tag ‘attachment_data[]’ >
<
= file_field_tag ‘attachment_data[]’ >
<
= file_field_tag ‘attachment_data[]’ %>

</p> <p> <%= f.label :ciudad %><br /> <%= f.text_field :ciudad %> </p> <p> <%= f.label :barrio %><br /> <%= f.text_field :barrio %> </p> <p> <%= f.label :direccion %><br /> <%= f.text_field :direccion %> </p> <p> <%= f.label :precio %><br /> <%= f.text_field :precio %> </p> <p> <%= f.submit ‘Update’ %> </p>

<% end %>

<%= link_to ‘Show’, @inmueble > |
<
= link_to ‘Back’, inmuebles_path %>

by pedro

please you can upload the folder app or send me by mail

please helpp!! i will apreciate

by tm

I’m not able to upload the app. Did you see my reply above? If so, what part is still giving you trouble?

—t

by pedro consuegra

ok i just work with more simple example that i will be implement in the same way on my first app

now it is work for me becouse my files are uploaded but i cant related them
i have products ans images
this are the migrate files

products

class CreateProducts < ActiveRecord::Migration
def self.up
create_table :products do |t|
t.string :title
t.text :description
t.integer :price

t.timestamps end end def self.down drop_table :products end

end

images I related this table with products with the field product_id

class CreateImages < ActiveRecord::Migration
def self.up
create_table :images do |t|
t.integer :parent_id, :size, :width, :height, :product_id
t.string :content_type, :filename, :thumbnail
t.timestamps
end
end

def self.down drop_table :images end

end

controller

def update
@product = Product.find(params[:id])
product_id = @product.id
@attachment = Image.new
params[:attachment_data] ||= []
params[:attachment_data].each do |file|
@attachment = Image.create({:uploaded_data => file}) unless file == ""
end

my view products/edit.html.erb

<h1>Editing product</h1>

<% form_for @product, :html => {:multipart => true} do |f| >
<
= f.error_messages %>

<p> <%= f.label :title %><br /> <%= f.text_field :title %> </p> <p> <%= file_field_tag ‘attachment_data[]’ %>

<%= file_field_tag ‘attachment_data[]’ >
<
= file_field_tag ‘attachment_data[]’ %>

</p> <p> <%= text_field_tag(‘product_id’,@product.id)%>? </p> <p> <%= f.label :description %><br /> <%= f.text_area :description %> </p> <p> <%= f.label :price %><br /> <%= f.text_field :price %> </p> <p> <%= f.submit ‘Update’ %> </p>

<% end %>

<%= link_to ‘Show’, @product > |
<
= link_to ‘Back’, products_path %>

how i can pass my @product.id to the field in my database product_id to each file that i upload in the view

please help me!!!

by tm

Your view and model look okay I think. Try this for your controller though:

1def update 2 @product = Product.find(params[:id]) 3 product_id = @product.id 4 @attachment = Image.new 5 params[:attachment_data] ||= [] 6 params[:attachment_data].each do |file| 7 @attachment = @product.images.create({:uploaded_data => file}) unless file == ”” 8 end 9end

Notice near the end the change from Image.create to @product.images.create. This will create the association you need.

Let me know how it goes.

—t

by pedro consuegra
<h1>Editing product</h1>

<% form_for @product, :html => {:multipart => true} do |f| >
<
= f.error_messages %>

<p> <%= f.label :title %><br /> <%= f.text_field :title %> </p> <p> <%= file_field_tag ‘attachment_data[]’ %>

<%= file_field_tag ‘attachment_data[]’ >
<
= file_field_tag ‘attachment_data[]’ %>

</p> <p> <%= text_field_tag(‘product_id’,@product.id)%> </p> <p> <%= f.label :description %><br /> <%= f.text_area :description %> </p> <p> <%= f.label :price %><br /> <%= f.text_field :price %> </p> <p> <%= f.submit ‘Update’ %> </p>

<% end %>

<%= link_to ‘Show’, @product > |
<
= link_to ‘Back’, products_path %>
how i can relate every file that i upload to my images database in the product_id field becouse now it always is null

by Waqas

Thanks a million.

It saved a lot of time for me. Good work!!!

by santosh

Thanks a lot.. u are so good..!!