2009-08-16 33 views
2

這裏是我的架構Rails的多態關係的link_to

class Menu < ActiveRecord::Base 
    belongs_to :menuable, :polymorphic => true 
end 

class Page < ActiveRecord::Base 
    has_one :menu, :as => :menuable 
end 

class Links < ActiveRecord::Base 
    has_one :menu, :as => :menuable 
end 

我想用的link_to在功能表視圖鏈接到一個多態類,例如

<%= link_to menu.name, menu.menuable %> 

這是有效的,但是當我想要的是產生鏈接時,它從數據庫中檢索可選擇的對象。你可以想象一下,如果我的菜單很大,這會讓我的應用程序崩潰。

當我將菜單字段捨棄爲多態時,Rails創建了menuable_type和menuable_id。我可以使用什麼來生成一個多態頁面的鏈接,而不是用一個巨大的開關語句編寫一個輔助函數(例如,如果我有大量的菜單「子類」?)

回答

6

問自問已經很久了,但最近我遇到了同樣的問題,解決辦法是使用polymorphic_url。您需要找到創建鏈接所需的路由名稱,例如「fast_car_path」,並將其從多態表中的* _type和* _id中刪除。例如,您有一系列評論,並希望鏈接到他們所屬的汽車。所以,如果* _type = FastCar我們

@comments.each do |comment| 
    link_to polymorphic_url(comment.commentable_type.tableize.singularize, :id => comment.commentable_id) 

這將產生「fast_car_path」不從數據庫下載的汽車。

我是一個菜單欄,我不知道這個建議有多好,但是我希望這會對某個人有所幫助。

1

你可以這樣做:

def my_menu_url(menu) 
    "/#{menu.menuable_type.tableize}/#{menu.menuable_id}" 
end 

如果您使用rails慣例命名與您的模型對應的控制器。

但不這樣做。你可以圍繞rails的路由機制工作,這很不好。

您應該使用:在您的發現者躍躍欲試加載選項您menuables:

Menu.all :include => :menuable 

在這種情況下,這是不夠的,你可能會使用某種形式的緩存。

+0

是否渴望加載工作的多態關係?它如何知道要加入的表,而不必先檢索菜單表? – tchen 2009-08-16 10:10:50

+0

我想最多你可以減少負載到存在的多態類型的數量。不幸的是,快速搜索顯示這不是ActiveRecord中的現有行爲。 :(或許是時候回到單表繼承了 – tchen 2009-08-16 10:15:17

+0

我認爲ActiveRecord首先加載所有的Menu記錄,第二步是爲第一個查詢的結果集中的每個menuable_type做一個查詢,我認爲單表繼承是在這種情況下沒有解決方案,因爲兩個模型差別很大。 – gregor 2009-08-16 19:03:19