2013-12-07 47 views
0

我有一個項目,其中客戶端堅持所有內容URL都是頂級的。這包括跨越非常不同的資源類型的網址,例如:頂級URL的多種資源類型

/products  #=> The Category "products" 
/privacy  #=> A content-managed SystemPage "privacy" 
/foo-bar-baz #=> An Article "foo bar baz" (user generated, no less) 

Obiviously,這是有問題的,提高至少兩個技術問題:

  1. 路由不能通過基於模式的辦法來處理
  2. 這些不同的內容片段需要在表格中是唯一的。

這並不是說它認爲Rails本身是對立的,並且肯定不符合框架的預期模式。

這就是說,我想知道是否有一個合理的理智的方式來實現這一點。

我的第一反應是維持「蛞蝓」,其映射蛞蝓如果以某種方式能夠資源類型,並通過塞在站點根執行查找,然後,向前請求到合適的控制器的一個表。我即將研究這種可能性,但我想我應該看看是否有其他人解決了這個問題(除了解僱客戶)。

回答

1

我想到轉發從一個控制器到另一個控制器的請求是不正確的。在Rails 3+中,您可以直接轉到Rack端點。實際上,控制器操作本身就是作爲機架終端實現的。

因此,爲了解決這個問題,我創建了一個簡單的Rack應用程序,該應用程序查找給定slug的Permalink,該slug具有對不同資源類型之一的多態引用。然後控制器確定並將env傳遞給動作。基本上是路由器中的中間件層。

本質:

class PermalinkRouter 
    def call(env) 
    req = ActionDispatch::Request.new(env) 

    # will throw if not found 
    permalink = Permalink.find_by!(slug: req.params['id']) 

    # resource_controller is a method of permalink, which constantizes 
    # a controller based on its resource_type. 
    permalink.resource_controller.action(:show).call(env) 
    end 
end 

get "/:id", to: PermalinkRouter.new 

無論何時創建資源類型中的一種本身產生的永久鏈接,並處理建立獨特的蛞蝓。

這超出了這個問題的範圍,但以這種方式將鏈接看作自己的資源,這使我可以做一些其他有趣的事情,包括實現永久鏈接「歷史」,其中舊鏈接生活在301重定向當前的資源URL。

+0

酷解決方案,讓我思考! – DeeY

1

在routes.rb中,你可以

match '/*', :controller => proc { (lookup the db here) } 

How to pass params to a block in Rails routes?

另一種方法是,試圖說服客戶接受前綴的網址像/ category_products或/ article_foo_bar,這是很容易設置的導軌方式

+0

+1謝謝,這讓我想到了,並讓我記住,控制器的行爲只是機架端點。但我不相信你*可以*傳遞一個proc到'controller'選項,至少不是在rails 4中。 – numbers1311407

+0

是的,你可以有:controller => proc {...}調用,但不幸的是,它似乎僅被評估一次併爲隨後的請求進行緩存。但我想應該可以重寫這個。 – DeeY