【问题标题】:Rails Defaults to "text/javascript" Content Type in Response to Unobtrusive JavaScript Form Built With form_forRails 默认为“text/javascript”内容类型以响应使用 form_for 构建的不显眼的 JavaScript 表单
【发布时间】:2014-07-26 11:06:14
【问题描述】:

我使用的是 Rails 4.1.1 和 Ruby 2.1.2p95。我使用 Slim 作为我的 HTML 模板语言(类似于 HAML)。我使用 Thin 作为我的 Rack 服务器。

我正在尝试制作一个完全 AJAX 的应用程序(我的要求之一是我不能重新加载页面)。

问题

我有一个如下所示的用户注册页面:

= form_for( User.new, url: user_path, remote: true ) do |f|
  = f.label :username
  = f.text_field :username, label: true
  = f.label :password
  = f.password_field :password, label: true
  = f.label :password_confirmation
  = f.password_field :password_confirmation, label: true
  = f.submit

我有一个如下所示的 UsersController 操作(出于本示例的目的):

  def create
    render html: "PRETEND A USER WAS CREATED"
  end

我有一个看起来像这样的响应处理程序(这实际上并不重要 - 可以说成功处理程序不会触发而错误处理程序会触发):

   $("#dynamic_body").on( "ajax:success", "[data-remote]", function( event, data, status, xhr ) {
      $("#dynamic_body").empty();
      $("#dynamic_body").append( data );
   });
   $("#dynamic_body").on( "ajax:error", "[data-remote]", function( event, xhr, status, error ) {
      $("#dynamic_body").empty();
      $("#dynamic_body").append( error );
   });

Rails 发送回一个响应,其中 Content-Type 标头设置为“text/javascript”。因此,浏览器尝试将响应解析为 JavaScript,这当然会失败,并导致错误事件而不是 AJAX 响应的成功事件。

我不喜欢的解决方案

我可以通过明确使用 Rails 来解决此问题,方法是在 form_for 调用中指定请求 URL 格式:

= form_for( User.new, url: user_path( format: :html ), remote: true ) do |f|
  ...

或通过在控制器操作中明确指定标头:

def create
    render html: "PRETEND A USER WAS CREATED", content_type: :html
end

但我很不高兴我什至不得不这样做。没有人要求 Rails 返回一个 javascript 响应。 Their own documentation says that the controller defaults to "text/html",这在大多数情况下显然是正确的,但在使用他们不引人注目的 JavaScript 工具时则不然。

我很想了解这里发生了什么,以及是否有任何方法可以配置我的应用程序,因此我不需要编写这些额外的解决方法。

提前感谢好人。

【问题讨论】:

  • 这似乎是特定于 Chrome 的问题。我对 Firefox 没有这种头痛。在每个浏览器中使用网络分析器,我看到 Chrome 选择将响应视为“文本/javascript”,导致问题,而 Firefox 将其视为“html”,并且工作正常。但是,仍然不知道原因是什么。在过去的几个小时里,我一直在浏览 jquery 和 jquery-ujs 文件,但一无所获。更改 JS 中的请求标头或 Rails 应用程序中的响应标头似乎没有任何效果。此外,问题是间歇性的。
  • 没关系。一旦我发表了该评论,我就会重新开始工作,它适用于 Chrome,不适用于 Firefox。

标签: javascript ruby-on-rails ajax content-type unobtrusive-javascript


【解决方案1】:

好吧,当我意识到它莫名其妙地断断续续时,我应该猜到这部分是缓存问题。基本上,解决方案是简单地强制 Rails 将请求视为 HTML 请求,但如果浏览器在您弄清楚之前已将响应缓存为 JavaScript,则在您清除浏览器缓存之前它将无法工作。

我将以下代码添加到我的 ApplicationController:

class ApplicationController < ActionController::Base
  ...

  # These two filters together should ensure we return HTML responses to the browser's AJAX reqeusts.
  before_filter :prevent_caching
  before_filter :default_request_format_html

  ...

  private

  ...

  def prevent_caching
    expires_now
  end

  def default_request_format_html
    request.format = "html"
  end
end

这些是最小的形式,可以根据您的需要变得更智能(例如,有条件地强制请求格式)。 default_request_format_html 回调是更关键的回调 - 如果你从一开始就正确,理论上你不应该需要缓存清除回调。

【讨论】:

    猜你喜欢
    • 2014-04-21
    • 2013-02-21
    • 2021-11-19
    • 2011-06-05
    • 2011-03-31
    • 2011-06-12
    • 1970-01-01
    • 1970-01-01
    • 2020-09-06
    相关资源
    最近更新 更多