Rails Ajax Image Uploading Made Simple with jQuery

Last week, as part of getting Bloggity rolling with the key features of WordPress, I realized that we needed to allow the user to upload images without doing a page reload. Expecting a task as ordinary as this would be well covered by Google, I dutifully set out in search of “rails ajax uploading” and found a bunch of pages that either provided code that simply didn’t work, or claims that it couldn’t be done without a Rails plugin.

Not so. If you use jQuery and the jQuery-form plugin.

The main challenge in getting a AJAX uploading working is that the standard remote_form_for doesn’t understand multipart form submission, so it’s not going to send the file data Rails seeks back with the AJAX request. That’s where the jQuery form plugin comes into play. Here’s the Rails code for it:

<% remote_form_for(:image_form, :url => { :controller => "blogs", :action => :create_asset }, :html => { :method => :post, :id => 'uploadForm', :multipart => true }) do |f| %>
 Upload a file: <%= f.file_field :uploaded_data %>
<% end %>

Here’s the associated Javascript:

$('#uploadForm input').change(function(){
 $(this).parent().ajaxSubmit({
  beforeSubmit: function(a,f,o) {
   o.dataType = 'json';
  },
  complete: function(XMLHttpRequest, textStatus) {
   // XMLHttpRequest.responseText will contain the URL of the uploaded image.
   // Put it in an image element you create, or do with it what you will.
   // For example, if you have an image elemtn with id "my_image", then
   //  $('#my_image').attr('src', XMLHttpRequest.responseText);
   // Will set that image tag to display the uploaded image.
  },
 });
});

And here’s the Rails controller action, pretty vanilla:

 @image = Image.new(params[:image_form])
 @image.save
 render :text => @image.public_filename

As you can see, all quite straightforward with the help of jQuery. I’ve been using this for the past few weeks with Bloggity, and it’s worked like a champ.

38 Replies to “Rails Ajax Image Uploading Made Simple with jQuery”

  1. Hi Bill, pretty informative tutorial… I had a thing to confirm….
    Aren’t we supposed to add something like in our /app/views/layouts/application.html.erb file….? . Here the file_name_having_js_code would be the file code for javascript as shown above.. I had seen this when basically we make use of jquery.. as per the railscast by Ryan B(http://railscasts.com/episodes/136-jquery).. Just wanted to confirm its addition in the above case also and whether I am actually doing it correctly..

    Thanks for the blog..

  2. thanks for this great post. i’ve been sweating on this for too long. and its the most simple solution of the lot.
    no flash, no iframes, no bulky plugins
    instead of a text response i threw in a partial and fed the object to it and ran append on the complete option and it works a treat.
    thanks again

  3. Thanks for this clear tutorial!

    The article needs an update though: ‘remote_form_for’ was removed from recent Rails versions, use ‘form_for’ with ‘:remote => true’ option instead.

    Also, ‘:url => { :controller => “blogs”, :action => :create_asset }’ generated an URL starting with ‘/assets?’ in my case.
    To avoid this, I used a simple route name as a parameter, which gives ‘:url => some_route_path’.

    Cheers,
    Samy

Leave a Reply

Your email address will not be published. Required fields are marked *