如何限制Rails路由文件中的资源格式

时间:2009-09-03 16:14:02

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

在Rails中路由资源时,可选的format属性会自动附加到生成的路由中。这样可以将所涉及的资源请求为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]}

有没有办法实现本机或通过插件?

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

5 个答案:

答案 0 :(得分:6)

如果要将这些路由限制为特定格式(例如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

答案 1 :(得分:5)

由于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

答案 2 :(得分:3)

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

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

如果用户请求html或json,它将按原样执行,但其他任何内容都将呈现“无效格式”文本。

答案 3 :(得分:1)

在任何一种情况下你都不想要HTTP 500错误吗?就像在你的例子的第二行,如果有人请求JSON而不是HTML或XML不是错误代码返回相应的响应?

答案 4 :(得分:0)

而不是:

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以外的任何视图,则所有其他格式如果请求将失败。