Rails 3.1 is awesome. CoffeeScript is great. The jQuery addition is brilliant. But recently I came across a simple problem that took quite a while to figure out and with all these additions being fairly new, there was not much online help available, so I had to turn to the source code.
So what was the problem? How do we dynamically modify the AJAX request data with rails using a link_to
. If I was using pure jQuery the solution would be as simple as,
$.ajax('/some/path', {
type: 'POST',
data: { foo: 'bar' },
success: function() { .. },
error: function() { .. }
});
But since I was trying to keep it Railsy and use link_to
to create a POST request, there were a few hurdles. Initially, I was trying to use the ajax:beforeSend
event callback which was useless for this task, as all form data gets set before this callback is made by Rails. The only use of this callback would be to abort the ajax request altogether if you suddenly discovered something. So I had to use the ajax:before
event. But inside the ajax:before
callback, we are only passed an event object totally unrelated to ajax, so to set custom ajax data, I had to checkout how any data gets passed to jQuery.ajax
by Rails in the first place. Here’s the relevant snippet from Rails UJS. Stripped out the form handling part as we’re dealing with a link here.
if (rails.fire(element, 'ajax:before')) {
if (element.is('form')) {
...
} else {
method = element.data('method');
url = element.attr('href');
data = element.data('params') || null;
}
...
}
So Rails looks for custom data inside the params
data object of the element triggering the ajax request which is where I had to implant it. The CoffeeScript code for intercepting the ajax request and injecting the data dynamically looked like,
$ ->
$('#my_link').bind('ajax:before', ->
$(this).data('params', { foo: 'bar' })
)
Or if you don’t like CoffeeScript for some reason, here’s the equivalent in JavaScript.
$(function() {
$('#my_link').bind('ajax:before', function() {
$(this).data('params', { foo: 'bar' });
});
});
The corresponding link in rails erb was,
<%= link_to 'Foo', foo_path, method: :post, remote: true, id: 'my_link' %>
This new syntax of creating hashes in Ruby 1.9 is cool and almost similar to JavaScript’s object literals.