2011-12-12 3 views
2

유무 STI 클래스 : 각 클래스레일 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 

및 경로 : FirstTypePageController에 의해 FirstTypePage을 처리하는 방법

resources :user 
    resource :page 
end 

SecondTypePageController by SecondPathPage 단일 경로에서?

사용자/1 페이지/2에 의해 처리되고/"2 페이지의"타입 "FirstTypePage" 이다 FirstTypePageController 경우 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

했다. 뭔가가 : 컨트롤러 => User.controller_for_page (: user_id) ?? – potapuff

답변

1

route.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 :

show.html 그러나

class PagesControllerStrategy 

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

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

, 내가보기 만 수준에 동작을 분할 할 수 좋을 것 .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