在后退按钮点击呈现的原始javascript

Ste*_*ton 11 ajax jquery ruby-on-rails

我们的团队最近提出了一个最初的边缘案例问题,当用户从具有某种javascript呈现的页面(无论是Ajax,标签等)中单击浏览器的后退按钮时,将显示原始javascript.要重新创建,我们按照以下步骤操作:

  • 访问用户作业应用程序索引
  • 单击管理作业发布页面上的按钮
  • 点击标签(使用bettertabs gem)
  • 单击浏览器的后退按钮

之前的步骤将显示:

(function() {

  $(".job_applications").html("<li class=\"job_posting_application\">\n
    ...
    ...
    ...
    ...
  );

}).call(this);
Run Code Online (Sandbox Code Playgroud)

在一些命中或未命中的情况下,您不需要在返回上一页之前单击选项卡,但它仍然会呈现原始javascript.在一天结束时,似乎最后渲染的模板正在被缓存,这在浏览器的部分是正常的和预期的,但导致我认为是一个更大的问题.

Rails指南在" 布局和渲染 "部分中说明,特别是关于模板的MIME类型:

默认情况下,Rails将使用MIME内容类型text/html(或者如果使用:json选项则使用application/json,或者使用:xml选项的application/xml)来提供渲染操作的结果.

基于Rails默认值,我们的控制器的索引操作应该呈现我们的index.html.slim模板.但是,在拖尾服务器日志的同时对该页面进行非远程调用(例如,直接导航到浏览器中的页面)时,我们注意到它实际呈现index.js.coffee.下面是我们的控制器操作,请注意我们没有明确响应html或js格式,因为我们可能应该考虑此页面中的重叠功能:

def index
  @company_id, @division_id, @job_posting_id = params[:company_id], params[:division_id], params[:job_posting_id]

  # API requests are made here to instantiate @job_posting, et al.,
  # but are not shown for brevity

  authorize! :manage, @job_posting

  @survey = @job_posting.survey
  @job_applications = @job_posting.job_applications(sort_column, sort_direction)
end
Run Code Online (Sandbox Code Playgroud)

但是,在此设置下,index.html.slim 基于Rails默认值进行渲染.添加respond_to块时,缓存似乎仍然有效,控制器可能不关心respond_to块的存在:

def index
  ...
  ...
  respond_to do |format|
    format.html
    format.js
  end
end
Run Code Online (Sandbox Code Playgroud)

即使明确地,虽然有点臭,告诉每种格式呈现不同的模板,但似乎js.coffee模板优先于html.slim模板:

def index
  ...
  ...
  respond_to do |format|
    format.html { render template: "users/job_posting_applications/index" }
    format.js { render template: "users/job_posting_applications/ajax" }
  end
end
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,直接导航到浏览器中的页面(换句话说,不进行远程Ajax调用),服务器日志将呈现ajax.js.coffee,即使Rails默认为html,除非另有说明.

所有这些都说,以下是其他一些发现:

Started GET "/users/companies/1/divisions/18/job_postings/349421/applications" for 127.0.0.1 at 2012-10-03 19:55:26 -0400
Processing by Users::JobPostingApplicationsController#index as JSON
Run Code Online (Sandbox Code Playgroud)

(你可以参考上面这个贴图中显示的整个请求)

为什么它作为JSON处理超出了我,考虑到我们没有在此请求上提供任何JSON,并且没有针对此路由的默认格式的路由规范:json.

此外,在调试request.format此操作中的值时,它将返回application/json.

呈现的另一个场景是在另一个users/company_admin_metrics#index仅包含index.html.slim模板的控制器()内.导航到此页面时,服务器日志显示它users/company_admin_metrics/index.html.slim在其中呈现layouts/users.当我创建一个空白的js.coffee模板时:

$ touch app/views/users/company_admin_metrics/index.js.coffee
Run Code Online (Sandbox Code Playgroud)

并直接导航到该索引页面,服务器日志显示它呈现users/company_admin_metrics/index.js.coffee,这进一步暴露了有关模板呈现优先级的某个潜在问题.

有没有人遇到类似的问题可能会为此提供潜在的解决方案?

我们的堆栈

以下是这个特定问题的基本参与者的一小部分列表:

  • Rails 3.2.6
  • 咖啡轨3.2.1
  • Bettertabs 1.2.6

此请求取决于通过解析JSON并返回Ruby对象的客户端gem对我们的作业发布API的请求,但这些请求不会与此特定应用程序耦合,从而导致应用程序具有内容类型application/json对于如上所述的这种请求.

小智 10

我认为你需要.js在ajax请求中将格式扩展名附加到URL.

可能发生的是用户正在使用html请求来执行index操作.然后ajax正在点击相同的URL /动作但请求javascript.当用户单击后退按钮时,浏览器无法区分两者之间的差异,因此使用最新的(javascript响应)./job_applicationsGET

  • 我不得不将.json添加到ajax调用中并且它有效 (2认同)

Jos*_*ach 5

最近开始在带有Rails 4.2.4的Chrome浏览器中看到此确切问题。似乎是一个众所周知且备受争议的问题。我们的团队通过将Vary标头添加到xhr请求中来解决该问题:

class ApplicationController < ActionController::Base
  after_action :set_vary_header

  private

  # Fix a bug/issue/by-design(?) of browsers that have a hard time understanding
  # what to do about our ajax search page. This header tells browsers to not cache
  # the current contents of the page because previously when someone filtered results,
  # went to the listing's external site, then hit Back, they'd only see the last
  # ajax response snippet, not the full listings page for their search.
  #
  # Heated multi-year discussion on this issue in Chrome
  # https://code.google.com/p/chromium/issues/detail?id=94369
  #
  # And continued by the Rails team:
  # https://github.com/rails/jquery-ujs/issues/318
  # https://github.com/rails/jquery-rails/issues/121
  def set_vary_header
    if request.xhr?
      response.headers["Vary"] = "accept"
    end
  end
end
Run Code Online (Sandbox Code Playgroud)