Rails not choosing the right layout for javascript requests

坚强是说给别人听的谎言 提交于 2019-12-10 12:04:45

问题


I have two different layouts in my app, one for javascript (AJAX) requests and one for regular requests.

# application.html.haml for non-js requests (abbreviated)
!!!
%html
  %head
  %body
    = yield

# and application.js.coffee for js requests
App.modal """<%= yield %>""" # creates a javascript modal

Any link with :remote => true should in theory use the javascript layout. This DOES work on certain occasions, but does not work on others.

It works for this link:

%li= link_to "Login", new_user_session_path, remote: true

# log output:
Started GET "/users/sign_in?&authenticity_token=KwyFmzGgR7Rdx3dudJDvw8b5rngvVDrwfTpYLPIPjEI=" for 127.0.0.1 at 2012-01-27 03:29:41 -0500
Processing by Devise::SessionsController#new as JS
  Parameters: {"authenticity_token"=>"KwyFmzGgR7Rdx3dudJDvw8b5rngvVDrwfTpYLPIPjEI="}
  Rendered devise/shared/_links.erb (0.9ms)
  Rendered devise/sessions/new.html.haml within layouts/application (6.3ms)
Completed 200 OK in 167ms (Views: 165.9ms | ActiveRecord: 0.0ms)

# output in the javascript console:
XHR finished loading: "http://localhost:3000/users/sign_in?&authenticity_token=KwyFmzGgR7Rdx3dudJDvw8b5rngvVDrwfTpYLPIPjEI=".

But does not work for this one:

%li= link_to "Account", edit_user_registration_path, remote: true

# log output:
Started GET "/users/edit?&authenticity_token=KwyFmzGgR7Rdx3dudJDvw8b5rngvVDrwfTpYLPIPjEI=" for 127.0.0.1 at 2012-01-27 03:31:24 -0500
Processing by Devise::RegistrationsController#edit as JS
  Parameters: {"authenticity_token"=>"KwyFmzGgR7Rdx3dudJDvw8b5rngvVDrwfTpYLPIPjEI="}
  User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
  MobilePhone Load (0.3ms)  SELECT "mobile_phones".* FROM "mobile_phones" WHERE "mobile_phones"."user_id" = 1 LIMIT 1
  Rendered devise/registrations/edit.html.haml within layouts/application (6.7ms)
Completed 200 OK in 157ms (Views: 154.4ms | ActiveRecord: 0.6ms)

# output in the javascript console:
XHR finished loading: "http://localhost:3000/users/edit?&authenticity_token=KwyFmzGgR7Rdx3dudJDvw8b5rngvVDrwfTpYLPIPjEI=".

After some simple debugging, I realized that the second request is hitting application.html.haml (wrong!), while the first one is hitting application.js.coffee (correct!). Both are being processed successfully by ajax.

I am a bit stumped here. I am hoping that I am making a simple mistake that somebody will be able to point out!

Thanks!

P.S. I am running rails 3.2.1 (and previously tried on 3.1.3 with same issue)

EDIT: Not sure if it makes a difference, but I am using the mootools-rails driver: https://github.com/kevinvaldek/mootools-ujs/blob/master/Source/rails.js. The accepts header is being set properly to "text/javascript".


回答1:


I was having the same issue, I tried with a new rails 3.2.7 from scratch and as I used application.haml instead of application.html.erb, remote links was not working. I tried this work around:

  1. Convert application.haml to a partial, rename application.haml to _application.haml
  2. In application.html.erb just one line:

    <%= render 'application' %>
    



回答2:


As for the layout you should specify it explicitly on the controller. Maybe you can change the name application.js.coffee to another name and add layout 'new_name' on the top of the controller.




回答3:


If you're using jQuery UJS then try adding a

 data-type="script"

attribute to your link tag. This will set the dataType of the jQuery request which in turn sets the Accepts: header of your http request. Rails usest that to guess the appropriate response type for your request.

See this blog post for some background information: http://www.alfajango.com/blog/rails-3-remote-links-and-forms-data-type-with-jquery/




回答4:


This is what I had to do to get this to work: (and has nothing to do with the javascript library)

# whatever_controller.rb
def index
  respond_to do |format|
    format.js   # renders index.html.haml inside application.js.haml layout
    format.html # renders index.html.haml inside application.html.haml layout
  end
end

Alternatively, you could just rename the template for the action to index.js.haml instead of index.html.haml, which would work for ajax requests without using respond_to. However, that would mean that search engines and browsers without javascript enabled would not be able to access the page.

Another method that would also work is to use respond_with:

# application_controller.rb
respond_to :html, :js

# whatever_controller.rb
def index
  respond_with # will render the appropriate layout
end


来源:https://stackoverflow.com/questions/9030826/rails-not-choosing-the-right-layout-for-javascript-requests

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!