David Harbage
David Harbage

Reputation: 697

Rails link_to with remote: true processing html instead of js after page refresh

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

Upvotes: 15

Views: 17477

Answers (6)

lukas
lukas

Reputation: 1

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

So make sure it isn't inside another form.

Upvotes: 0

CWarrington
CWarrington

Reputation: 789

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.

Upvotes: 0

user1130176
user1130176

Reputation: 1878

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

Upvotes: 0

GMA
GMA

Reputation: 6096

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)

Upvotes: 29

AmitF
AmitF

Reputation: 1437

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 %>

Upvotes: 8

druuu
druuu

Reputation: 1716

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.

Upvotes: 0

Related Questions