2009-07-13 26 views
0

我在Rails應用程序中使用文本永久鏈接作爲資源的ID,獲得了RESTful設置。在Ruby on Rails中創建新資源時驗證沒有路由重疊

此外,還有一些特殊的命名路線以及它與命名的資源如重疊:

# bunch of special URLs for one off views to be exposed, not RESTful 
map.connect '/products/specials', :controller => 'products', :action => 'specials' 
map.connect '/products/new-in-stock', :controller => 'products', :action => 'new_in_stock' 

# the real resource where the products are exposed at 
map.resources :products 

Product模型使用permalink_fu基於名稱產生永久鏈接,並ProductsController進行查找在訪問時的永久鏈接字段。這一切都很好。

但是,當在數據庫中創建新的Product記錄時,我想驗證生成的永久鏈接確實是而不是與特殊的URL重疊。

如果用戶嘗試創建一個名爲specialsnew-in-stock甚至像newedit正常的Rails的RESTful資源的方法的產品,我想控制器來查找路由配置,該模型對象上設置錯誤,驗證失敗了新記錄,而不是保存它。

我可以硬編碼一個已知非法固定鏈接名稱的列表,但這樣做似乎很麻煩。我寧願掛鉤到路由中來自動執行。

(控制器和型號名稱變更爲保護無辜者,並使其更容易回答,實際設置更復雜得多,這個例子)

回答

1

那麼這個工作,但我不知道它是多麼可愛。主要問題是將控制器/路由邏輯混合到模型中。基本上,您可以在模型上添加自定義驗證以進行檢查。這是使用無證路由方法,所以我不確定它將會如何穩定。任何人有更好的想法?

class Product < ActiveRecord::Base 
    #... other logic and stuff here... 

    validate :generated_permalink_is_not_reserved 

    def generated_permalink_is_not_reserved 
    create_unique_permalink # permalink_fu method to set up permalink 
    #TODO feels really ugly having controller/routing logic in the model. Maybe extract this out and inject it somehow so the model doesn't depend on routing 
    unless ActionController::Routing::Routes.recognize_path("/products/#{permalink}", :method => :get) == {:controller => 'products', :id => permalink, :action => 'show'} 
     errors.add(:name, "is reserved") 
    end 
    end 
end 
+0

這似乎是要走的路,但我不會擔心模型中的路由/控制器邏輯,並試圖將其分離出來。事實是,在你的系統中,模型*確實依賴於路由 - 如果它與另一條路由發生衝突,它就不是一個有效的模型。 – ideasasylum 2009-07-14 11:26:02

0

您可以使用本來不存在的路線。這樣一來,如果有人爲某個標題選擇了一個保留字,它就不會有什麼區別。

map.product_view '/product_view/:permalink', :controller => 'products', :action => 'view' 

而在你的觀點:

product_view_path(:permalink => @product.permalink) 
+0

不幸的是,這不是一種選擇。這些網址已經建立起來了,具有相關的SEO價值,以及依賴於它們的其他系統配置等,所以它們不能輕易改變。 一切都按原樣工作,只是如果用戶創建了重疊的名稱,該產品會被系統有效忽略。 – madlep 2009-07-14 01:14:26

0

這是一個更好的做法是明確自己管理的URI這樣的原因,並避免意外暴露你不想路線。