module UploadProgress::ClassMethods

Action Pack Upload Progress for multipart uploads

The UploadProgress module aids in the process of viewing an Ajax driven upload status when working with multipart forms. It offers a macro that will prepare an action for handling the cleanup of the Ajax updating including passing the redirect URL and custom parameters to the Javascript finish handler.

UploadProgress is available for all multipart uploads when the upload_status_for macro is called in one of your controllers.

The progress is stored as an UploadProgress::Progress object in the session and is accessible in the controller and view with the upload_progress method.

For help rendering the UploadProgress enabled form and supported elements, see ActionView::Helpers::UploadProgressHelper.

Automatic updating on upload actions

class DocumentController < ApplicationController   
  upload_status_for  :create

  def create
    # ... Your document creation action
  end
end

The upload_status_for macro will override the rendering of the action passed if upload_id is found in the query string. This allows for default behavior if Javascript is disabled. If you are tracking the upload progress then create will now return the cleanup scripts that will terminate the polling of the upload status.

Customized status rendering

class DocumentController < ApplicationController   
  upload_status_for  :create, :status => :custom_status

  def create
    # ... Your document creation action
  end

  def custom_status
    # ... Override this action to return content to be replaced in
    # the status container
    render :inline => "<%= upload_progress.completed_percent rescue 0 %> % complete", :layout => false
end

The default status action is upload_status. The results of this action are added used to replace the contents of the HTML elements defined in upload_status_tag. Within upload_status, you can load the Progress object from the session with the upload_progress method and display your own results.

Completion of the upload status updating occurs automatically with an after_action call to finish_upload_status. Because the upload must be posted into a hidden IFRAME to enable Ajax updates during the upload, finish_upload_status overwrites the results of any previous render or redirect_to so it can render the necessary Javascript that will properly terminate the status updating loop, trigger the completion callback or redirect to the appropriate URL.

Basic Example (View):

<%= form_tag_with_upload_progress({:action => 'create'}, {:finish => 'alert("Document Uploaded")'}) %>
<%= upload_status_tag %>
<%= file_field 'document', 'file' %>
<%= end_form_tag %>

Basic Example (Controller):

class DocumentController < ApplicationController
  upload_status_for :create

  def create
    @document = Document.create(params[:document])
  end
end

Extended Example (View):

<%= form_tag_with_upload_progress({:action => 'create'}, {}, {:action => :custom_status}) %>
<%= upload_status_tag %>
<%= file_field 'document', 'file' %>
<%= submit_tag "Upload" %>
<%= end_form_tag %>

<%= form_tag_with_upload_progress({:action => 'add_preview'}, {:finish => 'alert(arguments[0])'}, {:action => :custom_status})  %>
<%= upload_status_tag %>
<%= submit_tag "Upload" %>
<%= file_field 'preview', 'file' %>
<%= end_form_tag %>

Extended Example (Controller):

class DocumentController < ApplicationController
  upload_status_for :add_preview, :create, {:status => :custom_status}

  def add_preview
   @document = Document.find(params[:id])
   @document.preview = Preview.create(params[:preview])
   if @document.save
     finish_upload_status "'Preview added'"
   else
     finish_upload_status "'Preview not added'"
   end
  end

 def create
   @document = Document.new(params[:document])

   upload_progress.message = "Processing document..."
   session.update

   @document.save
   redirect_to :action => 'show', :id => @document.id
 end

 def custom_status
   render :inline => '<%= upload_progress_status %> <div>Updated at <%= Time.now %></div>', :layout => false
 end

Environment checklist

This is an experimental feature that requires a specific webserver environment. Use the following checklist to confirm that you have an environment that supports upload progress.

Ruby:
Web server:
FastCGI bindings:
Apache/Lighttpd FastCGI directives:
config/environment.rb:
Development log:

Public Instance Methods

upload_status_for(*actions) click to toggle source

Creates an after_action which will call finish_upload_status creating the document that will be loaded into the hidden IFRAME, terminating the status polling forms created with form_with_upload_progress.

Also defines an action upload_status or a action name passed as the :status option. This status action must match the one expected in the form_tag_with_upload_progress helper.

# File lib/upload_progress/lib/upload_progress.rb, line 184
def upload_status_for(*actions)
  after_action :finish_upload_status, :only => actions
  
  define_method(actions.last.is_a?(Hash) && actions.last[:status] || :upload_status) do
    render(:inline => '<%= upload_progress_status %>', :layout => false)
  end
end