提问人:Mark Thomson 提问时间:10/17/2023 最后编辑:Mark Thomson 更新时间:10/20/2023 访问量:85
js 请求 Rails 6.0 应用程序渲染 html 模板而不是 js
js requests to Rails 6.0 app render html template instead of js
问:
我正在将一个遗留的 Rails 5.0 应用程序迁移到(希望)7.x。我没有太多麻烦就到了 5.2.x。我目前正在尝试升级到 6.0,但我的控制器操作有问题,这些操作设置为根据请求类型呈现 js 或 html。例如,在一般形式的标准“新”操作中:
def new
@post = Post.new
respond_to do |format|
format.js
format.html
end
end
如果使用 发送 jQuery ajax 请求,则服务器将呈现模板而不是 。控制台确认请求是作为 js 请求接收的,但 html 正在呈现,例如dataType: 'script'
views/posts/new.html.erb
views/posts/new.js.coffee
Started GET "/posts/new" for 127.0.0.1
Processing by PostsController#new as JS
Rendering posts/new.html.erb
Rendered posts/new.html.erb
但是,如果我从视图目录中删除 new.html.erb,则服务器会根据需要呈现 js 模板。
Started GET "/posts/new" for 127.0.0.1
Processing by PostsController#new as JS
Rendering posts/new.js.coffee
Rendered posts/new.js.coffee
我在许多不同的控制器/操作上看到了相同的行为。
关于我缺少什么有什么建议吗?FWIW,我没有使用 webpacker,只是普通的链轮。和 ruby 2.6.6。我从 5.2.x 与 javascript 相关的唯一更改是添加一个包含以下内容的文件:assets/config/manifest.js
//= link_tree ../images
//= link_tree ../javascripts .js
//= link_directory ../stylesheets .css
编辑: 同样是 FWIW,我在 #js 和 #html 方法中添加了一个带有测试语句的块 -
respond_to do |format|
format.js {puts "calling js"}
format.html {puts "calling html"}
end
并确认 #js 方法是被调用的方法,即使它正在呈现 HTML 模板。
答:
您可能需要在 JQuery ajax 请求中显式设置标头。由于您有两种格式的模板。我相信 Rails 偏爱 HTML 格式,只要请求认为它是可以接受的。accepts
评论
respond_to
accepts
text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01
text/javascript
jQuery.ajax
在不深入的情况下,这里有一个问题:
https://github.com/rails/rails/blob/v6.0.0/actionview/lib/action_view/path_set.rb#L48
def find(*args)
find_all(*args).first || raise(MissingTemplate.new(self, *args))
# ^^^^^^
end
# where `find_all` returns
# =>
# [
# #<ActionView::Template app/views/posts/new.html.erb locals=[]>,
# #<ActionView::Template app/views/posts/new.js.coffee locals=[]>
# ]
html
在此过程中添加了格式,作为 :
https://github.com/rails/rails/blob/v6.0.0/actionview/lib/action_view/lookup_context.rb#L291-L294 的后备js
if values == [:js]
values << :html
@html_fallback_for_js = true
end
这绝对是一个 rails 错误。我不确定它是什么时候修复的,但一切正常。rails v7
如果你打算升级,可以尝试一些后来的 rails 6 版本,看看他们当时是否修复了它。现在,我可以想到几个解决方案:
respond_to do |format|
format.js { render formats: :js } # explicitly render js format only
format.html
end
除此之外,您可以覆盖方法并修复模板的顺序以对应于格式的顺序 - :find_all
[:js, :html]
# config/initializers/render_coffee_fix.rb
module RenderCoffeeFix
def find_all(path, prefixes = [], *args)
templates = super
_, options = args
ordered_templates = options[:formats].map do |format|
templates.detect { |template| template.format == format }
end.compact
ordered_templates
end
end
ActionView::PathSet.prepend(RenderCoffeeFix)
评论
new.js.erb
new.js.erb