【问题标题】:How to limit the resource formats in the Rails routes file如何限制 Rails 路由文件中的资源格式
【发布时间】:2010-11-25 08:32:04
【问题描述】:

在 Rails 中路由资源时,可选的格式属性会自动附加到生成的路由中。这样可以将相关资源请求为 XML、HTML 等。实际允许的格式通常在控制器中使用respond_to 进行描述。

但在许多情况下,您只想支持 HTML,并且在每个控制器的每个操作中都写 respond_to :html 感觉像是一种开销。因此,如果在 routes.rb 文件中构建路由时已经有一种方法可以限制允许的内容类型,那就太酷了,例如

map.resources :users, :formats => :html
map.resources :users, :formats => [:html, :xml]
map.resources :users, :formats => {:index => :html, :show => [:html, :xml]}

有没有办法通过本机或插件来实现这一点?

附:解决此问题的常用方法是忽略该问题并且不要在操作中使用respond_to。但这实际上并不限制允许的内容类型。相反,它只期望在视图目录中存在每个可能的内容类型的模板。如果请求时不存在,系统将抛出 HTTP 500 错误。

【问题讨论】:

    标签: ruby-on-rails rest routing content-type


    【解决方案1】:

    如果要将这些路由限制为特定格式(例如 html 或 json),则必须将它们包装在范围内。不幸的是,在这种情况下,约束不能按预期工作。

    这是一个这样的块的例子......

    scope :format => true, :constraints => { :format => 'json' } do
      get '/bar' => "bar#index_with_json"
    end
    

    更多信息可以在这里找到:https://github.com/rails/rails/issues/5548

    这个答案是从我之前的答案复制过来的。

    Rails Routes - Limiting the available formats for a resource

    【讨论】:

      【解决方案2】:

      由于 Rails 使用等效的通配符来处理格式“.:format”,因此在路由方面防止事情变得有点困难。

      取而代之的是,在前置过滤器中捕获任何非 HTML 请求是一种非常简单的方法。这是可能的一种方式:

      class ApplicationController < ActionController::Base
        before_filter :check_format
      
        private
      
          def check_format
            if request.format != Mime::HTML
              raise ActionController::RoutingError, "Format #{params[:format].inspect} not supported for #{request.path.inspect}"
            end
          end
      
      end
      

      ActionController::RoutingErrors 作为 404 错误处理,这是明智的。 如果您确实有需要支持 HTML 以外的其他内容的操作,只需使用:

      skip_before_filter :check_format, :only => ACTION_NAME
      

      【讨论】:

        【解决方案3】:

        我相信你能够做到这样的事情:

        respond_to do |format|
          format.html
          format.json { render :json => @things }
          format.any { render :text => "Invalid format", :status => 403 }
        end
        

        如果用户请求 html 或 json,它会按照应有的方式进行处理,但其他任何内容都会呈现“无效格式”文本。

        【讨论】:

        • 这可行,但我认为他想从路线中删除 :format
        【解决方案4】:

        在任何一种情况下,您都不想出现 HTTP 500 错误吗?就像在您的示例的第二行中一样,如果有人请求 JSON 而不是 HTML 或 XML 不是错误代码返回适当的响应?

        【讨论】:

        • 不,500 错误意味着服务器出现问题。如果不支持内容类型,则不是服务器错误 - 这是客户端错误(客户端不应该请求它)。 406 将是正确的响应代码。请参阅“HTTP 响应代码”:sitepoint.com/blogs/2008/02/04/restful-rails-part-i
        • 当然,如果您要在 URL 末尾标记 .xml 或 .html 并且不支持该格式,那么您应该返回 404 not found。通过为每个内容类型创建 URL 来忽略 conneg 的使用,然后在接受标头中没有有效的内容类型时窃取响应代码,这似乎有点厚颜无耻!
        • 好吧,你可能有一点道理——尽管这实际上是 Rails 开箱即用的工作方式。但是,这不是我的问题的重点。我仍然想在一个中心位置(最好是路由文件)指定这个 - 无论是在错误时返回 404 还是 406
        • 抛开要返回的正确代码。我认为关键是按照惯例,它正在做它应该做的事情,你所建议的似乎是为了配置而配置。
        【解决方案5】:

        而不是做:

        def some_action
          ...
          respond_to do |format|
            format.html
            format.json { whatever }
            format.any { whatever  }
          end
        end
        

        只需使用:

        def some_action
          ...
        end
        

        Rails 将默认查找 some_action.html.erb 或任何请求的格式。如果您没有定义除 html 之外的任何视图,那么所有其他格式都将在请求时失败。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-04-10
          • 2015-06-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多