2011-12-12 49 views
2

有無性病類:Rails的STI:單路徑,不同的控制器

class Page < ActiveRecord::Base 
    belongs_to :user 
end 

class FirstTypePage < Page 
end 

class SecondTypePage < Page 
end 

控制器爲每個類,

class PageController < AplicationCorroller 
end 

class FirstTypePageController < PageController 
end 

class SecondTypePageController < PageController 
end 

和工藝路線:

resources :user 
    resource :page 
end 

如何通過FirstTypePageController處理FirstTypePage ,SecondTypePage by SecondTypePageController在單個路徑上?

用戶/ 1 /頁/ 2通過處理: FirstTypePageController如果 「2頁」 類型是 「FirstTypePage」, 和由SecondTypePageController如果 「2頁」 類型 「SecondTypePage」?

UPDATE:我的解決方案:

match 'user/:user_id/page/:action', 
    :controller=>'page/first_type_page', 
    :constraints=>PageConstraints.new('FirstTypePage') 
    match 'user/:user_id/page/:action', 
    :controller=>'page/second_type_page', 
    :constraints=>PageConstraints.new('SecondTypePage') 

class PageConstraints 

    @@cache ||= {} 

    def initialize o_type 
    #@mutex = Mutex.new 
    @o_type = o_type 
    end 

    def matches?(request) 
    user_id = request.params[:user_id] 
    #add Mutex lock here 
    unless page_type = @@cache[user_id] 
     page_type = User.find(user_id).do_some_magik_to_suggest_type 
     @@cache[page_id] = page_type 
     @@cache.shift if @@cache.size > 1000 
    end 
    page_type == @o_type 
    end 

end 

我覺得這個解決方案將工作速度快在頁面類型少量的,我們可以管理存儲容量,用於航線上大量的

+0

換句話說,可以控制在路由級別運行選擇。 lIke:controller => User.controller_for_page(:user_id)?? – potapuff

回答

1

我可以看到一個選項 - 預載所有routes.rb頁面併爲每個頁面定義特殊路由。

resources :users do |user| 
    Page.all do |page| 
    if page.first_type? 
     # ... routes to first_type_page_controller 
    else 
     # ... 
    end 
end 

另一種解決辦法是使用戰略圖案在PageController(無需使用FirstTypePageController等)。

pages_controller.rb:

before_filter :choose_strategy 

def show 
    @strategy.show 
end 

private 

def choose_strategy 
    @strategy = PagesControllerStrategy.new(self, page) 
end 

def page 
    @page ||= Page.find params[:id] 
end 

pages_controller_strategy.rb:

class PagesControllerStrategy 

    def initialize(controller, page) 
    @controller = controller 
    @page = page 
    end 

    def show 
    # do what you what with controller and page 
    end 
end 

不過,我建議你拆就只有視圖級行爲:

show.html .haml:

- if page.first_type? 
    = render 'pages/first_type' 
- else 
    // ... 

編輯:

我剛剛發現另一個解決方案,可以幫助你 - 自定義約束。 http://railsdispatch.com/posts/rails-3-makes-life-better

我不確定這是否適用於您的情況,但我認爲這是值得玩更多的路線。

+0

「爲每個頁面定義特殊路線」 - 我認爲,它會在大量頁面上具有不良的性能,並佔用大量內存 – potapuff

+0

在第二種解決方案中,我們失去了所有ActionController的魔法,就像過濾器和其他 – potapuff

+0

這就是爲什麼我我寧願分割視圖中的邏輯。 – cutalion

0

你可以用before_filter來做,但是將STI模型分成不同的控制器並不是好的解決方案。我完全同意下一個報價

這可能並不總是適用,但我還沒有看到STI與多個控制器配合良好的情況。如果我們使用STI,我們的對象共享一組ID和屬性,因此應該以基本相同的方式訪問(通過某些屬性查找,按某種屬性排序,限制爲管理員等)。如果演示文稿變化很大,我們可能想要從控制器呈現不同的模型特定視圖。但是如果對象訪問變化太大以至於它建議單獨的控制器,那麼STI可能不是正確的設計選擇。

了這裏http://code.alexreisner.com/articles/single-table-inheritance-in-rails.html

+0

你的意思是使用before_filter重定向到適當的控制器?它可以在路線上完成嗎? – potapuff

+0

我同意這個報價,購買多態模型我會有同樣的路由問題。 – potapuff

+0

是的,在過濾器重定向前 如果你需要自動檢測模型類型的路線,我認爲這是不可能的 – mibon

相關問題