2009-09-03 44 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