DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world
Multiple Upload Using Attachment_fu
Here is my case, I got a simple Task (to-do) list app where you can upload up to 2 photo images for each task. Obviously you will need attachment_fu installed on your Rails app before continue.
Task model
class Task < ActiveRecord::Base has_many :photos, :dependent => :destroy validates_presence_of :description end
Photo model
class Photo < ActiveRecord::Base
belongs_to :task
has_attachment :content_type => :image,
:storage => :file_system,
:max_size => 500.kilobytes,
:resize_to => '384x256',
:thumbnails => {
:large => '96x96>',
:medium => '64x64>',
:small => '48x48>'
}
validates_as_attachment
end
TaskService model
class TaskService
attr_reader :task, :photo
def initialize(task, photos)
@task = task
@photos = photos
end
def save
return false unless valid?
begin
Task.transaction do
@photos.each do |photo|
if photo.new_record?
@task.photo.find(photo).destroy if @task.photos.include?(photo)
photo.task = @task
photo.save!
end
end
@task.save!
true
end
end
end
def update_attributes(task_attributes, photo_file)
@task.attributes = task_attributes
unless photo_file.nil?
@photos = []
photo_file.each do |file|
@photos << Photo.new(:uploaded_data => file)
end
end
save
end
def valid?
@task.valid? && valid_photos?
end
def valid_photos?
@photos.each do |photo|
return false unless photo.valid?
end
true
end
end
New / edit task view
<% form_for(@task, :html => { :multipart => true }) do |f| %>
<%= error_messages_for :task, :photo %>
...
<p>
<%= label :task, :photo, 'Photos' %><br />
<%= file_field_tag 'photo_file[]' %><br />
<%= file_field_tag 'photo_file[]' %>
</p>
...
Tasks controller
...
def create
@task = Task.new(params[:task])
build_photos(params[:photo_file])
@service = TaskService.new(@task, @photos)
respond_to do |format|
if @service.save
flash[:notice] = 'New Task created.'
format.html { redirect_to(@task) }
format.xml { render :xml => @task, :status => :created, :location => @task }
else
format.html { render :action => "new" }
format.xml { render :xml => @task.errors, :status => :unprocessable_entity }
end
end
end
def update
@task = Task.find(params[:id])
@photos = @task.photos
@service = TaskService.new(@task, @photos)
respond_to do |format|
if @service.update_attributes(params[:task], params[:photo_file])
flash[:notice] = 'Task was successfully updated.'
format.html { redirect_to(@task) }
format.xml { head :ok }
else
format.html { redirect_to(tasks_url) }
format.xml { render :xml => @task.errors, :status => :unprocessable_entity }
end
end
end
...
protected
def build_photos(photo_file)
@photos = []
photo_file.each do |file|
@photos << Photo.new(:uploaded_data => file) unless file.blank?
end
end
I believe this snippet need some refactoring, but I hope you find it useful enough.






Comments
William Notowidagdo replied on Wed, 2007/08/15 - 11:34pm
Snippets Manager replied on Wed, 2009/07/29 - 9:00am