2013-03-13 54 views
5

我在Rails應用程序中使用了許多不同的模型。我見過許多網站使用應用程序範圍的段塞路由方法。這是什麼意思?如何爲Rails應用程序創建應用程序範圍的slug路由?

http://example.com/nick-oneill <-- This points to a User object 
http://example.com/facebook <-- This points to a Company object 
http://example.com/developers <-- This points to the users#index page 

我知道to_param和應用程序中創建讀者喜愛的蛞蝓,但我不知道的方法有root級別的蛞蝓爲各種不同的物體。您可以將其視爲與Facebook的Graph API類似:存在不同的對象類型,但所有對象類型都存在於https://graph.facebook.com/object-id

任何洞察將非常感謝!

+0

hmm。你可能有一張slu table子的桌子,你可以保留它的類型。那麼只需添加一個檢查該類型的路由並嘗試基於該路由重定向。 – jvnill 2013-03-13 01:08:26

+0

這似乎有點過分,因爲現在我需要提出兩個請求來獲取對象,不是嗎? – 2013-03-13 01:09:27

+0

是。我不知道Rails如何區分slu unless,除非它們已經被定義,或者至少有一些可以區分它們的模式。 – jvnill 2013-03-13 01:15:21

回答

10

可能有辦法做到這一點與freindly_id,但我認爲與友好id的問題是事物的範圍由模型。

如果我想要真正地在網站範圍內猛擊,我會創建一個與我的模型有多態關係的slu table表。

Sluggable_type和sluggable_id然後一個slug字段與完整的永久鏈接/ slug。

+---------------------------------------------+ 
| sluggable_type | sluggable_id |  slug | 
|  user  |  13  | users/john | 
+---------------------------------------------+ 

現在我能做的做一個通配符包羅萬象的路線或運行時創建了我所有的蛞蝓的路線和強制路由刷新當模型更新,這是該sluggable控制之下。

routes.rb

get "/*segments", 
       :controller => 'slugs', 
       :action => 'dynamicroute' 

現在,在您SlugsController實現諸如

def dynamicroute 
    segments = params[:segments] 
    slugs.find_by_slug(segments) 
    slug.sluggable_type.constantize.find(slug.sluggable_id) #retrive real record 
    #some magic to handle the slugged item maybe redirect to the appropriate 
    #controller or somehow call the show view for that controller 
end 

OR

routes.rb

begin 
    Slug.all.each do |s| 
    begin 
     get "#{s.slug}" => "#{s.sluggable_type.demodulize.pluralize.camelize}#show" 
    rescue 
    end 
    end 
rescue 
end 

如果一個方法您使用第二個方法來路由確保您撥打

YOUR_APP_NAME::Application.reload_routes!

編輯任何猛擊記錄刷新路由表之後。

我們遇到了類似的問題,我們可能會試着用這種方法來試試。

+0

該死的,打我在我寫作時類似的答案。不過,看起來您的路由方法可能比我的天真方法更深思熟慮。 – imakewebthings 2013-03-13 19:18:48

+0

我們在生產中使用它,雖然只用於頁面,但我認爲它應該像這樣擴展?這很好,因爲你看到'rake routes'中所有的段落路線# – 2013-03-13 19:19:57

+0

@j_mcnally,你使用生產中的第一個還是第二個版本?第二種方法出現WAYYYY更乾淨。當我必須從控制器方法中加載另一個控制器時,它變得非常髒。我在這裏想到的一個例外可能會創建一個名爲SluggedController的中間控制器,該控制器繼承了ApplicationController的子類,然後爲其他控制器子類SluggedController。好奇地在這裏得到你的想法! – 2013-03-14 18:28:37

2

我可能會接近這個如下,至少在第一遍:

  • 使用friendly_id或類似蛞蝓產生每個模型涉及
  • 胡克一個包羅萬象的路線/([-_a-zA-Z0-9]+)和它指向像EntitiesController#show
  • 胡克爲/developers指向更高的優先級路線Users#index
  • 在EntitiesController#顯示:

    @entity = User.find(params[:id]) or Company.find(params[:id]) or raise ActionController::RoutingError.new('Not Found')

  • 然後,根據你得到的實體類型:

    render "VIEW_PATH_BASED_ON_ENTITY_CLASS/show"

我也訂購認定從最多到最少頻繁訪問(猜先,然後稍後使用數據來調整訂單)。

最後,可能很明顯,但要確保您在每張表格中爲slug列編制索引,因爲您經常會爲每個請求執行多次查找。

FWIW我很想知道更好的方法來解決這個問題;這只是我最初如何解決問題。

+0

感謝凱爾!我已經upvoted你的答案,但我在等待,看看還有什麼我得到...試圖找到最好的辦法在這裏:) – 2013-03-13 18:48:48

0

我的第一反應是創建一個新的Slug模型。這種模式將有一個多態belongs_to

belongs_to :sluggable, :polymorphic => true 

在至少該表將有:

  • value - 或者比這一些更好的名字。 slu itself本身的價值。
  • sluggable_type and sluggable_id - 多態外鍵。

你的公司,用戶等車型車型只會有一個毛坯:

has_one :slug 

這給我們了蝙蝠的幾個優點:

  • 它現在容易做出對slug值有獨特的限制。如果slu were被保留爲所有不同可緩存模型的屬性,那麼您的唯一約束將不得不檢查所有其他可坍縮表的唯一性。造成一段糟糕的時光。
  • 路由很簡單,因爲您可以使用正常的resource路由脫離根級別名稱空間。您可能希望將其保持在路由文件的最終位置,儘管其他更具體的路由優先。 編輯:這種路由基本上是j_mcnally建議的第一種路由方法。
  • 所有的slu logic logic logic,like like like what what what what is is is is is is is is is this this this this this this this this良好的問題分離而不是污染用戶模型。特別是如果slu rules的規則對每個人都是一樣的,就像他們在這裏一樣。

就控制器的工作方式而言,我會選擇Kyle所說的,然後鍵入sluggable_type字段以找到要渲染的視圖。

相關問題