【问题标题】:Methods for limiting the Rails render format to html将 Rails 渲染格式限制为 html 的方法
【发布时间】:2010-12-12 20:51:14
【问题描述】:

我有一个只有 html 模板的 Rails 2.1.2 站点,例如jobs.html.erb,所以当我请求一个宁静的资源时:

www.mysite.com/jobs/1

如果我要求,它会以 html 呈现我的工作:

www.mysite.com/jobs/1.xml

我得到错误:

模板丢失 缺少模板 视图路径中的jobs/show.xml.erb c:/workspace/mysite/app/views

更糟糕的是我还可以请求类似的东西

www.mysite.com/jobs/1.xyz

确实我看到了错误:

模板丢失 缺少模板 视图路径中的作业/show.xyz.erb c:/workspace/mysite/app/views

要严格呈现 html 内容,告诉 Rails 我不想呈现 .html.erb 文件以外的任何内容的最简洁和最简单的方法是什么。

需要注意的是:

  • 我的一些控制器操作包含对 render() 方法的条件调用,而其他操作使用默认的 Rails 行为,即如果您不调用 render(),那么名为 youraction.html.erb 的模板将被渲染。
  • 我的代码没有使用 responds_to() 方法

如果解决方案不在 render/responds_to 级别,那就太好了,因为我必须修改大量操作。也许有一种方法可以配置 Rails 以便只呈现 html 模板?

【问题讨论】:

    标签: ruby-on-rails rest format mime render


    【解决方案1】:

    在您的路线中,您可以简单地删除该行:

    map.connect ':controller/:action/:id.:format'
    

    并且“.xyz”将不再被路由,导致404错误/。

    【讨论】:

    • 删除这一行并不能解决 Rails 3.2.6 中的问题:它已经被注释掉了,但仍然出现 Template Missing 错误。
    【解决方案2】:

    您可以使用 Rails Per-Action Overwrite 功能。这是什么? --> 还可以通过将块传递给 respond_with 来覆盖标准资源处理,并指定该操作要覆盖的格式:

    class UsersController < ApplicationController::Base
    
      respond_to :html, :xml, :json
    
      # Override html format since we want to redirect to a different page,
      # not just serve back the new resource
      def create
        @user = User.create(params[:user])
        respond_with(@user) do |format|
          format.html { redirect_to users_path }
        end
      end
    end
    

    :except And :only 选项

    您还可以传入 :except 和 :only 选项以仅支持特定操作的格式(就像使用 before_filter 一样):

    class UsersController < ApplicationController::Base
      respond_to :html, :only => :index
      respond_to :xml, :json, :except => :show
      ...
    end
    

    :任何格式

    如果您仍想在个人操作中使用 respond_to,请使用可用作通配符匹配任何未指定格式的 :any 资源格式:

    class UsersController < ApplicationController::Base
    
      def index
    
        @users = User.all
    
        respond_to do |format|
          format.html
          format.any(:xml, :json) { render request.format.to_sym => @users }
        end
      end
    end
    

    【讨论】:

    • Jared,您能否更具体地说明三个选项中的哪一个仅适用于 Rails 3!我在 Rails 2.3.4 上运行,并且 :any 选项有效。
    【解决方案3】:

    如果您不想使用 responds_to,可以这样做:

    class ApplicationController < ActionController::Base
      before_filter :allow_only_html_requests
    
      ...
    
      def allow_only_html_requests
        if params[:format] && params[:format] != "html"
          render :file => "#{RAILS_ROOT}/public/404.html"
        end
      end
    
      ...
    
    end
    

    这将在所有请求之前运行,并且只让那些根本不指定格式或指定 html 格式的请求通过。所有其他人都得到404'd。如果您想返回 406 不可接受,您可以创建一个 public/406.html。

    【讨论】:

    • 这实际上并没有返回 404,但它只是将 404.html 呈现为 200 响应。您需要添加:status =&gt; 404(或:status =&gt; :not_found)。同样,对于 406,您需要使用 :status =&gt; 406(或 :status =&gt; :not_acceptable)。
    • 如果请求使用 'accept' 标头来请求响应类型,这也会失败,因为它没有存储在 params 中
    【解决方案4】:

    Ben 的解决方案有效。

    不过,请考虑 responds_to 解决方案。它更简洁,因为当您不可避免地需要为 JavaScript json 或 xml 调用打开一个操作时,它提供了灵活性。那你就不用加了

    skip_before_filter :allow_only_html_requests, :only => [:show]
    

    我个人喜欢 respond_to 块;它非常具有描述性。

    respond_to do |wants|
      wants.html
     end
    

    块中未指定的任何格式将自动导致返回 HTTP 406 Not Acceptable。挺好的。

    【讨论】:

    • 同意。 responds_to 块开辟了一个灵活的世界,如果您可以花时间为每个控制器操作添加一个 .html 文件,这是一个更具前瞻性的解决方案。
    【解决方案5】:

    我收到了对 HTML 文件的图像格式无意义的请求,触发了带有 MissingTemplate 的 500。我在行动结束时制定了以下内容:

    def show
      # [...]
      respond_to :html
    end
    

    现在我们不会收到错误报告,而是向那个淘气的请求者发出 406。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-05
      • 2010-09-26
      • 2014-12-28
      • 1970-01-01
      • 1970-01-01
      • 2013-01-17
      • 1970-01-01
      • 2016-12-14
      相关资源
      最近更新 更多