2009-09-03 49 views
13

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

但在很多情况下,您只需要支持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错误。

回答

1

无论哪种情况下你不想要HTTP 500错误?就像您的示例的第二行一样,如果有人请求JSON而不是HTML或XML,那么错误代码是否会返回相应的响应?

+1

不,一个500错误意味着发生了错误的服务器上。如果内容类型不受支持,则不是服务器错误 - 这是客户端错误(客户端不应该请求它)。 406将是正确的响应代码。请参阅“HTTP响应代码”:http://www.sitepoint.com/blogs/2008/02/04/restful-rails-part-i/ – 2009-09-03 16:58:47

+0

当然,如果您打算在末尾标记.xml或.html该URL和该格式不被支持,那么你应该返回404找不到。通过为每种内容类型创建URL来忽略conneg的使用似乎有点厚颜无耻,但是当在accept头中没有有效的内容类型时窃取repsonse代码! – 2009-09-03 18:31:34

+0

好吧,你可能有一点 - 即使这实际上Rails是如何工作的。但是,这不是我的问题的重点。我仍然想在一个中心位置(最好是路由文件)中指定它 - 无论如何404或406返回错误 – 2009-09-03 18:47:09

3

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

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

如果用户请求HTML或JSON它会做到这一点,因为它应该,但任何东西都不会呈现“无效的格式”文本。

+0

这将工作,但我认为他想从路线 – 2011-05-16 09:20:08

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

+0

删除:格式我想他也想从路线中删除:格式 – 2011-05-16 09:18:37

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