views:

1556

answers:

2

I'm using the jQuery Form Plugin on a big ass form which includes some file fields. The back end is Ruby on Rails.

I'm having trouble getting Rails to recognize the POST request type to be 'text/javascript' even though I believe I am setting it correctly.

The form looks like:

<form id="listing_form" method="POST" enctype="multipart/form-data" action="/listings">
    <input type="text" size="30" name="listing[venue][phone]" id="listing_venue_phone"/>
    <input type="file" size="30" name="listing[venue][image]" id="listing_venue_image"/>
    ...plus tons of other fields

The js looks like:

$("#listing_form").ajaxForm({ dataType: 'script' });

And I also have declared:

jQuery.ajaxSetup({ 
    'beforeSend': function(xhr) {xhr.setRequestHeader('Accept', 'text/javascript')}
});

The request makes it to the controller, but the Rails respond_to block sees it as a normal html request. Also, Firebug shows a parser error and fails to display the request and response headers in the console.

If I remove the file field and POST the text fields only, the respond_to block handles the request as a js request and properly executes the create.js.erb file.

How can I get Rails to properly respond to the request? Thanks.

+2  A: 

Due to JavaScript security limitations it is impossible to send forms with (non-empty) file fields via XHR. The usual workaround is to "fake" ajax form submission by posting to a hidden iframe. I believe that is also what jQuery Form plugin does.

One way of making Rails treat these "fake" ajax form submissions as actual XHR requests would be adding a special parameter in jQuery Form plugin's beforeSubmit callback:

// ...
beforeSubmit: function(data) {
    data.push({name: 'accept_js', value: '1'});
}
// ...

Then in your controller use a before filter to set format of the request to :js when posted data contains the special parameter:

before_filter :set_ajax_request

# ...

private
  def set_ajax_request
    request.format = :js if params[:accept_js] == '1'
  end

Your respond_to method should now work as expected.

mtyaka
Hey thanks for your advice. However, the accept_js parameter disappears between adding it in beforeSubmit and hitting the Rails app. It might have to do with the iframe hack. Tracking it down now...
cinematic
I followed the screencast: http://blog.edgecase.com/2009/6/15/ajax-file-uploads-made-easy-screencast,and got it working. Basically, I added a <$= hidden_field_tag :format, 'js' %> to the form, and installed the plugin. Works perfectly. Thanks for your suggestion, it helped me understand what's going on and sent me in the right direction.
cinematic