April 11, 2012
How to upload multiple files in Ruby on Rails (No JS required)

Today I was working on uploading multiple images in one of my Rails project. I would like to share what I did.

I was using Rails 3.0.10 with carrierwave although I am pretty sure it can be used with paperclip and may be other gems like dragonfly.

Here is my view file:

<% form_for @screenshot,:url=>{:action=>"create"},:html => {:multipart => true}  do |f| %>
  <input type="hidden" id ="project_id" name="project_id" value="<%=params[:project_id]%>" >

  <div class = "field"> 
    <%= f.label :screenshot %><br />
    <%= f.file_field :screenshot, :multiple => true %>  
  </div>

  <div class="action">
    <%= f.submit "Upload"%>
  </div> 
<% end %>

My Model is as follow:

# Project Screenshot Model
class ProjectScreenshot < ActiveRecord::Base
  belongs_to :project_master
  mount_uploader :screenshot, ScreenshotUploader
end 

Upto this point everything was pretty self explanatory and simple. And here goes the most important part. Controller

def create
  params[:screenshot_length] = params[:project_screenshot][:screenshot].length
  params[:project_screenshot_screenshot] = params[:project_screenshot][:screenshot]
  params[:project_screenshot_screenshot_0] = params[:project_screenshot][:screenshot][0]
  params[:project_screenshot_screenshot_1] = params[:project_screenshot][:screenshot][1]

  @screenshots = Array.new
  i = 0
params[:project_screenshot][:screenshot].each do |screenshot|
    @screenshots[i] = ProjectScreenshot.new
    @screenshots[i].screenshot = screenshot
    @screenshots[i].project_master_id = params[:project_id]
    i = i + 1
end
screenshot_flag = false
@screenshots.each do |screenshot|
    if screenshot.save
        screenshot_flag = true
    else
        screenshot_flag = false
    end
end
  if screenshot_flag
    flash[:notice]="Successfully Added Screenshot"
    redirect_to :back
  else
    flash[:notice]="Some problem in screenshot. Not Saved."
    redirect_to :back
  end
end

As you can see in the first five line of controller; I tried to figure out how do I get parameter from form to my controller.

Once I knew that images are passed in the parameter in an array of params[:project_screenshot][:screenshot], rest of the story was very simple. I created an array and looped through param array, created an object of ProjectScreenshot (model name in my case) and saved them.

I spent a quite a bit of hours to figure out how to upload multiple images in Rails but finally It seems pretty easy to me. I decided to write a blog about this because I didn’t find any decent solution on the internet about this.

My next goal is to upload the same images with progress bar using jQuery File Upload or uploadify. My personalĀ favoriteĀ is first one because of it’s use of html5 and lack of flash.