15

I have a search page in my app, where there is an ajax search form. The search form works properly, passing parameters to the model to filter the search, and the model returning a collection of results. Upon search submit, @results are rendered on the page. Each @result then has a link to an action on it, like:

<%=link_to "Message", message_user_path(:id => user.id), :remote => true%>

Where this action in the controller is:

respond_to :js, :html
def message
  @user_id = params[:id]
  @user = User.find_by_id(@user_id)
  respond_to do |format|
    format.html
    format.js
  end
end

and this responds with message.js.erb, which triggers a messaging panel to pop up with a message to the user. All of this is working correctly, checking the log I see the correct get request sent, and the correct format being processed:

Started GET "/users/3/message"
Processing by UsersController#message as JS

However, if I refresh the page and try to click the same link that was working before, I get the error Template is Missing. Checking the log, I see that now there are two requests sent, first an html then the same js request.

Started GET "/users/4/message"
Processing by StudentsController#message as HTML
...
Completed 406 Not Acceptable in 3ms (ActiveRecord: 1.0ms)

Started GET "/users/4/message"
Processing by StudentsController#message as JS

The html request throws the missing template error. Does anyone know why refreshing the page causes rails to attempt to respond with an html request to a remote link?
EDIT: routes.rb

resources :students do
    member do
      get 'message'
    end
end
David Harbage
  • 687
  • 3
  • 8
  • 25
  • remove `respond_to :js, :html` in your controller, you don't need it – Thanh Nov 13 '12 at 09:31
  • indeed, you can remove `html` in your processable formats, or force the link to call js : `link_to "Message", message_user_path(:id => user.id, :format => :js), :remote => true` – m_x Nov 13 '12 at 10:12
  • oh, and you may have simple browser cache issues. Have you checked if the actual html code changed when you refreshed the page ? – m_x Nov 13 '12 at 10:14
  • @m_x: Trying to force :format => :js uses an http request to fetch and display the message.js file. I've since changed my method to do everything on the client end, as I couldn't seem to get around this issue. I think it must have something to do with cache issues, but I've tried it on multiple browsers on multiple machines and cleared my cache to no avail. Could it be something in my app? – David Harbage Nov 15 '12 at 07:08
  • sorry, i don't know where this could come from. – m_x Nov 15 '12 at 08:12

6 Answers6

28

Does your app/assets/javascripts/application.js contain

//= require jquery
//= require jquery_ujs 

?

And your erb contains <%= javascript_include_tag "application" %>?

I was just struggling with a problem like this for HOURS and the last of those two points fixed it; I saw the first point mentioned in some other questions so I'll repeat it here.

Hope that helps.

(Credit where credit's due)

Community
  • 1
  • 1
GMA
  • 5,816
  • 6
  • 51
  • 80
8

What solver it for me was adding :format => "js"

So in your case:

<%=link_to "Message", message_user_path(:id => user.id, :format => "js"), :remote => true %>
AmitF
  • 1,287
  • 13
  • 9
0

In general, when you use link_to on a particular button or so, when you press the button, as js request is send to the controller, but also searches for the respective .js.erb file and so on.

druuu
  • 1,676
  • 6
  • 19
  • 36
0

My solution was to replace

format.json do

with

format.js do

you can troubleshoot the request by setting a breakpoint (i use pry) in the controller and then look at the variable

request.format
user1130176
  • 1,772
  • 1
  • 23
  • 33
0

For newer versions of Rails, this should be fixed where using remote: true within the link_to code, as the original poster was doing, will only look for a .js format to respond with. As others have said, if you never need an html response, then you can remove that from your code all together; you won't even need a respond_to, respond_with, etc as Rails will auto respond with JS looking for the template you already have made. So your controller code would look like this:

def message
  @user_id = params[:id]
  @user = User.find_by_id(@user_id)
end

And the link would still be this:

<%=link_to "Message", message_user_path(:id => user.id), :remote => true %>

Or this would work as well (my preferred way of syntax):

<%=link_to "Message", message_user_path(id: user.id), remote: true %>

This code will call the controller action which will look for the template message.js.erb.

I know this question is old now, but for anyone looking for answers and using current Rails 6+ (I'm using 7.0.0alpha), and if you are getting this same type of issue where both HTML and JS templates are being requested; check that turbolinks is not what is causing the issue. Sometimes turbolinks can cause a request to be sent twice and it may be sending the first request as an HTML request.

CWarrington
  • 659
  • 5
  • 12
0

My form with remote: true was inside another form and I didn't know it.

So make sure it isn't inside another form.

Thom A
  • 88,727
  • 11
  • 45
  • 75
lukas
  • 1
  • 2