ruby-on-rails js请求Rails 6.0应用渲染html模板而不是js

sy5wg1nm  于 2023-10-21  发布在  Ruby
关注(0)|答案(2)|浏览(152)

我正在将一个遗留的Rails 5.0应用程序迁移到7.x(希望如此)。5.2.x没有太大的问题。我目前正试图升级到6.0,我有一个问题,控制器的行动,设置为呈现js或html取决于请求的类型。例如,在一般形式的标准“new”操作中:

def new
  @post = Post.new
  respond_to do |format|
    format.js
    format.html
  end
end

如果一个jQuery Ajax请求是用dataType: 'script'发送的,服务器会呈现views/posts/new.html.erb模板而不是views/posts/new.js.coffee。控制台确认该请求是作为js请求接收的,但正在呈现html,例如。

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,只是普通的插件。Ruby2.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模板。

blpfk2vs

blpfk2vs1#

不深入,这里有一个问题:

  • 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,作为js的备用格式:

  • https:github.com/rails/rails/blob/v6.0.0/actionview/lib/action_view/lookup_context.rb#L291-L294*
if values == [:js]
  values << :html
  @html_fallback_for_js = true
end

这绝对是一个rails bug。我不确定它是什么时候修复的,但在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)
gxwragnw

gxwragnw2#

您可能需要在jQuery Ajax请求中显式设置accepts头。因为你有两种格式的模板。我相信Rails更喜欢HTML格式,只要请求认为它是可以接受的。

相关问题