views:

79

answers:

2

I'm fairly new to rails so forgive me if I'm making some dumb mistake here. I'm trying to make an ajax call with link_to, and respond to a js.erb template. It isn't going so well. The link renders correctly:

 <a href="/show" data-method="post" data-remote="true" rel="nofollow">Click</a>

The barebones show action:

def show
  respond_to do |format|
    format.js {render :layout => false}
  end
end

And show.js.erb just contains an alert for testing. When I click the link I'm unceremoniously led to localhost:3000/show, which is completely blank. It seems to be a GET request despite declaring the method as POST, and I get a "406 Not Acceptable" error.

Started GET "/show" for 127.0.0.1 at Tue Oct 12 19:58:17 -0500 2010
Processing by PostsController#show as HTML
Completed 406 Not Acceptable in 1ms

edit: I did a request.xhr test in the show action, and apparently no ajax call is being made. So what am I doing wrong here?

+1  A: 

From your description it looks like your link doesn't have the unobtrusive JavaScript listeners attached to it and so the browser is just following the href of the link. So the problem seems to be on the client side.

But your question doesn't give enough details to give a straight answer, so I'll just list all the steps that I'd take to investigate this.

First, to make this work you have to include all required javascripts and csrf meta tags inside your layout <head> tag. It's best to do it with:

<%= javascript_include_tag :defaults %>
<%= csrf_meta_tag %>

If you have this, load the page and look at the source if it's really generating the links correctly. You should see something like this:

<head> 
    <script src="/javascripts/prototype.js?1285857859" type="text/javascript"></script> 
    <script src="/javascripts/effects.js?1285857859" type="text/javascript"></script> 
    <script src="/javascripts/dragdrop.js?1285857859" type="text/javascript"></script> 
    <script src="/javascripts/controls.js?1285857859" type="text/javascript"></script> 
    <script src="/javascripts/rails.js?1285857859" type="text/javascript"></script> 
    <script src="/javascripts/application.js?1285934960" type="text/javascript"></script> 
    <meta name="csrf-param" content="authenticity_token"/> 
    <meta name="csrf-token" content="b2HRysd23edj1/vrCSRDSac0seDFae3n2gCoTjt0="/> 
</head>

If they're there, I'd install Firebug Javascript debugger or use the Chrome developer tools, turn it on and see if there're any errors on the page when it's loaded and when you click the link. You can also view the requests sent and see if they're xhr then and there.

If it still doesn't work, open rails.js in Firebug and set a breakpoint before the piece of code that's responsible for attaching listeners on data-remote and/or data-method. This is the one:

document.on("click", "a[data-remote]", function(event, element) {
    if (event.stopped) return;
    handleRemote(element);
    event.stop();
  });

Set a breakpoint on the first line, and a second breakpoint inside the handler function. Then reload the page and see if it attaches the listener. Then click the link and see if the handler is fired. And then... it depends on what happens. Hopefully you can continue by yourself.

And just a general note - I think show action should be accessed with get not post.

-- EDIT --

I think the 406 not acceptable is returned because you don't have format.html in your respond_to block. If you add it, then it should just render the show.html.erb template.

Matt
I have firebug and yes, the correct js files are included. There are no relevant errors on page load or when I click the link. There are no xhr requests, just the 406 get request. I don't know how exactly I'm supposed to "see if it attaches the listener", but the handler function is fired.
herpderp
I just meant if the execution gets to the `document.on` line. So if the handler function is fired, does it get to the second line (`handleRemote(element)`)? If it does, try to debug it deeper to see why it doesn't send the xhr request.
Matt
I already figured out what the problem was, see below
herpderp
A: 

Aha, the problem was that jQuery was conflicting with prototype.js. I set it to noConflict mode and it worked.

herpderp
How did you come up with that solution? Was it just an "aha!" moment, or you debugged the code?
Matt