



UPDATE: Hands up I made a boo-boo, I had listed the variable that holds the token as ‘form_authentication_token’ and it should have been ‘form_authenticity_token’, many apologies for the inconvenience.
So I was trying my first ajax calls to a rails backend and I hit this ugly error -
ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken)
I hunted about on google till I found the answer. The problem is that Rails automagically adds a randomly generated token ( bunch of characters ) that it inserts into any forms created with any of the form helpers (form_for, form_tag etc). When the form is posted Rails checks the token is valid before processing the request.
This code
<h1>New productsetupinfo</h1> <% form_for(@productsetupinfo) do |f| %> <%= f.error_messages %> <p> <%= f.label :setup %><br /> <%= f.text_area(:setup, :cols=>"80",:rows=>"30") %> </p> <p> <%= f.label :note %><br /> <%= f.text_area(:note, :cols=> "64", :rows=>"1") %> </p> <p> <%= f.submit "Create" %> </p> <% end %> <%= link_to 'Back', productsetupinfos_path %>
Produces this html
<form action="/productsetupinfos" class="new_productsetupinfo" id="new_productsetupinfo" method="post"> <div style="margin: 0pt; padding: 0pt;"> <<< Authenticity Token automagically added here >>> <input name="authenticity_token" value="7054c89779d7c1b6ed64e5261b49de76d1539974" type="hidden"> </div> <p> <label for="productsetupinfo_setup">Setup</label><br> <textarea cols="80" id="productsetupinfo_setup" name="productsetupinfo[setup]" rows="30"></textarea> </p> ....<snip>
The problem with making an ajax call is that Rails doesn’t have the opperchancity to insert the authenticity token, so it’s up to you to do it manually. Fortunately you can access the authenticity token in your views using form_authenticity_token. You only need to make 2 changes to your code to get it working.
To test this we’ll create a page that doesn’t work and then fix it so it does.
First : Create a new Controller. From the root of your rails app
script/generate controller Authfix index js_responder
Next : Create methods in new controller
class AuthfixController < ApplicationController
def index
end
def js_responder
respond_to do |wants|
wants.js { render :text => 'AJAX successful - Barman! Lard for everyone!' }
end
end
end
And finally create the view
<html>
<head>
<<< You may need to change this to point to your jquery library >>>
<%= javascript_include_tag "jquery">
<script type="text/javascript">
$(document).ready(function()
{
$('#makecall').click(function()
{
$.post('/authfix/js_responder',{ somedata:'somedata' },function(data,status){ $("#response").html(data) },'text');
}
});
</script>
</head>
<body>
<input type="button" id="makecall" value="Press me" /><br />
<div id="response">Nowt yet</div>
</body>
</html>
Now run this and click the button and nothing will happen, if you check your logs you will see our friend the InvalidAuthenticityToken error rearing its head.
Btw, interestingly if you make an Ajax call and pass no data in the 2nd $.post argument it works fine.
To fix the problem you need to store the auth token in a js variable (if available) and automatically add it to any ajax calls
class AuthfixController < ApplicationController
def index
end
def js_responder
respond_to do |wants|
wants.js { render :text => 'AJAX successful - Barman! Lard for everyone!' }
end
end
end
And finally create the view
<html>
<head>
<<< You may need to change this to point to your jquery library >>>
<%= javascript_include_tag "jquery">
<script type="text/javascript">
$(document).ready(function()
{
<<< Store Authentication Token here >>>
var AUTH_TOKEN = "<%= protect_against_forgery? ? form_authenticity_token : '' %>";
<<< Automatically add token to ajax calls >>>
$.ajaxSetup({data:{authenticity_token : AUTH_TOKEN}});
$('#makecall').click(function()
{
$.post('/authfix/js_responder',{ somedata:'somedata' },function(data,status){ $("#response").html(data) },'text');
}
});
</script>
</head>
<body>
<input type="button" id="makecall" value="Press me" /><br />
<div id="response">Nowt yet</div>
</body>
</html>
Add the two lines above and re-run the app and you should now get a response after clicking the button.
Result.










More Options ...

Categories
Tag Cloud
Blog RSS
Comments RSS

Void (Default)
Life
Earth
Wind
Water
Fire
Lightweight