Multiple file upload with HTML5 and RailsAdmin (Ruby on Rails)
Yesterday I spent a few hours working on adding multiple file upload capabilities to the administrative panel of a website I am working on. The administrative panel of the website is built using RailsAdmin. RailsAdmin is a Rails engine that provides an easy-to-use interface for managing your data.
I needed the upload functionality for the Gallery section of the website. Each photo gallery has many photos and the website owner should be able to upload with ease multiple photos for each gallery. The ideal solution for this use case is to have a file upload field that accepts multiple files, so that the administrator could select a number of pictures from their computer and upload with a single click.
The last time I had to develop this functionality, I did it by integrating SWFUpload (JavaScript Library that wraps Flash Player’s upload function) with the Symfony framework.
This time I decided to use the HTML5 file input tag, with the multiple attribute. A quick search returned a blog post, quite close to what I need - Multiple file upload with Rails 3.2, paperclip, html5 and no javascript. What was left was to integrate that functionality with RailsAdmin’s custom actions.
Models
The first step is to create an Album
and Photo
models.
class Album < ActiveRecord::Base
attr_accessible :title
has_many :photos
accepts_nested_attributes_for :photos, :allow_destroy => true
attr_accessible :photos_attributes
end
class Photo < ActiveRecord::Base
attr_accessible :caption, :album_id, :file
belongs_to :album
has_attached_file :file, :styles => { :detailed => "1920x1920>", :thumb => "100x100>" }
end
Having those two models, RailsAdmin should automatically detect them and provide a simple upload functionality for the file field inside the Photo
model.
RailsAdmin Custom Action
The next step is to create a custom controller and view for the Multiple File upload action. I created a new Gem using the gist from RailsAdmin’s wiki:
rails plugin new rails_admin_multiple_upload -m https://gist.github.com/bbenezech/1621146/raw/5268788e715397bf476c83d76d335f152095e659/rails_admin_action_creator --skip-gemfile --skip-bundle -T -O -S -J --full
After that we amend the custom view for the action:
= simple_form_for(rails_admin.multiple_upload_url(@abstract_model.to_param), html: { multipart: true }) do |f|
= f.input :album_id, :as => :hidden, :input_html => { :name => "album_id", :value => @object.id }
= file_field_tag('album_photos_file', multiple: true, name: "album[photos_attributes][][file]")
= f.submit :submit, value: 'Upload', name: 'Upload', :class => 'btn btn-primary'
… as well as the rails_admin_multiple_upload.rb
file
class MultipleUpload < Base
RailsAdmin::Config::Actions.register(self)
register_instance_option :member do
true
end
register_instance_option :link_icon do
'icon-upload'
end
register_instance_option :http_methods do
[:get, :post]
end
register_instance_option :controller do
Proc.new do
@response = {}
if request.post?
@album = Album.find_by_id(params[:album_id])
@album.update_attribute(:photos_attributes, params[:album][:photos_attributes])
end
render :action => @action.template_name
end
end
end
We add the Gem to the project’s Gemfile:
gem 'rails_admin_multiple_upload', :path => '../rails_admin_multiple_upload'
RailsAdmin initialiser configuration
The last bit is to add the custom action to the member actions of the Album model. We only want to have the multiple upload button for the Album model, therefore we add the only
directive. This we do at the RailsAdmin initialiser: config/initialisers/rails_admin.rb
RailsAdmin.config do |config|
config.actions do
dashboard
index
new
multiple_upload do
only Album
end
show
edit
delete
end
end