views:

435

answers:

2

Hi all,

I have some javascript making an ajax call in my Rails site:

$.ajax({type: "PUT", url: url, data: { dummy: data }, complete: function(data) {}});

When Rails gets it, it throws back an ActionController::InvalidAuthenticityToken Error. I'd like to keep the protect_from_forgery stuff in there, if possible... But I'm at a loss for how can I pass the auth token from a javascript file?

Can anyone help me out?

+10  A: 

In your layout, add this before any other JS runs:

<script type="text/javascript"><!--
  function authToken(){
    return '<%= form_authenticity_token if protect_against_forgery? -%>';
  }
//--></script>

authToken is coded as a function so that it's less likely you'll accidentally overwrite it with other JavaScript.

In your main JS, you can then call authToken(), and it'll return your authenticity token as a string to include in your Ajax calls. For example:

$.ajax({
  type: 'PUT',
  url:  url,
  data: {
    foo: bar,
    authenticity_token: authToken()
  },
  complete: function(data){}
});

Note that if you use Rails' built-in form_for helper, it automatically adds the authenticity token in a hidden input. If you want to send all of the form's data, including the hidden auth token, you can simply use:

var $form = $('form');
$.ajax({
  url:      $form.attr('action'),
  type:     $form.attr('method'),
              // "get" or "post"; overridden by Rails' hidden "_method"
              // input value, e.g., "put"
  data:     $form.serialize(),
              // Includes hidden "authenticity_token" and "_method" inputs
  complete: function(data){}
});

This pattern is often useful when you've already written a form that works without JS, and you're adding an unobtrusive layer of JS that simply sends the form's data via Ajax.

Ron DeVera
Great, thanks a tonne! Worked like a charm.
Matt Grande
A: 

Thanks for the above solution.
I am using some standard forms in my site that don't use the rails form_tag so instead I simply added it as a hidden form element.

<form action="...">
    <%= hidden_field_tag 'authenticity_token', form_authenticity_token if protect_against_forgery? %>
    ... rest of form...
</form>

Works a treat.

Darren Greaves