2014-07-02 62 views
4

我有一個看起來像2條通配符路線:當URL有尾隨斜線與約束通配符路線,以結束與斜線

get '*country_path/', to: 'country#list', constraints: { country_path: /\/$/ } 
get '*country_path/:title', to: 'country#show' 

國家#列出應該被調用。例子:

www.example.com/usa/california/ 
www.example.com/usa/california/abc/ 

國家#秀應該叫時,它沒有結尾的斜線。示例:

www.example.com/usa/californa/travel 
www.example.com/usa/californa/average-income 

目前我的約束似乎不工作,因爲所有的請求都去國家#列表。

我的路線約束有什麼問題?

+0

這應該有助於http://stackoverflow.com/questions/6186780/trailing-slash-behavior-in-rails-application?rq=1 – Pavan

+0

@Pavan沒有真正幫助(不知道是否相同問題,我無法得到它的工作) – Blankman

回答

7

你應該問問自己,這是否是真正實現你所要做的最好的方法。一般網站不關心目錄中的尾部斜槓。例如:

www.facebook.com/username 

將帶你到作爲同一個地方:

www.facebook.com/username/ 

絕大多數的網站,這樣的工作,所以你想現在做的是針對Web約定。它肯定會對搜索引擎優化產生影響,如果你關心的話。即使你不這樣做,你應該考慮在測試這些路線時你將面臨的困難。你的測試會很脆弱,從長遠來看,這會造成很多挫折。

我的建議是:如果你想區分listshow,把它們放到URL中。例如:

www.example.com/usa/california/list 
www.example.com/usa/california/abc/list 

可以將用戶引導至country#list,以「加州」和「ABC」作爲參數。同樣的:

www.example.com/usa/californa/travel/show 
www.example.com/usa/californa/average-income/show 

可以把用戶帶到country#show。這很容易做到。它也更加標準和用戶友好。有關更多信息,請參見Rails Routing from the Outside In.

1

問題在於Rails在到達路由之前已將尾部/剔除,因此使用傳統方法無法匹配它。唯一的方法是使用advanced constraint。下面就爲你想要的工作:

# config/routes.rb 
class TrailingSlashMatcher 
    def matches?(request) 
    uri = request.env["REQUEST_URI"] 
    uri.present? && uri.end_with?("/") 
    end 
end 

Rails.application.routes.draw do 
    get '*country_path', to: 'country#list', :constraints => TrailingSlashMatcher.new 
    get '*country_path/:title', to: 'country#show' 
end 

(從here拍攝)。

這種方法的麻煩在於它不適用於所有情況。它適用於對服務器的實際請求,但在從測試中調用時可能會遇到問題。原因是REQUEST_URI env變量不是rack spec的一部分,因此不由測試框架設置。 env["PATH_INFO"]是強制性的,但刪除了尾隨/,所以在這裏沒有用。

總而言之,可能值得重新考慮路線的設計。匹配存在或不存在尾隨/是相當脆弱的。這也可能會導致您的用戶感到困惑(例如,當鏈接被複制/粘貼等)。是否沒有其他方式來區分列表和顯示請求(可能基於路線的深度)。

+0

好點,我也擔心。我支持動態層次結構,因此無法知道URL的哪個部分是類別,哪個是文件名。 – Blankman

+0

在這種情況下,我可能會做類似於@ ege-ersoz建議的內容,並在列表路徑的末尾保留一個字符串。 另一種方法是有2階段路由過程。在路線中,將所有內容路由到單個控制器操作。這個動作可以作爲第二級路由器 - 它可以進行必要的查找以確定它是一個列表還是一個show動作,然後相應地發送到控制器上的另一個方法。 – AlexT