Rails Sti:单路径,不同的控制器

时间:2011-12-12 14:57:57

标签: ruby-on-rails ruby routing 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

路线:

resources :user
  resource :page
end

如何通过FirstTypePageController处理FirstTypePage,通过SecondTypePageController在单个路径上处理SecondTypePage?

user / 1 / page / 2由以下人员处理:  FirstTypePageController如果&#34;第2页&#34; type是&#34; FirstTypePage&#34;, 并通过SecondTypePageController如果&#34;第2页&#34; type是&#34; SecondTypePage&#34; ?

更新:我的解决方案:

  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

我认为这个解决方案可以在少量页面类型上快速运行,我们可以管理内存大小,用于大量页面上的路由

2 个答案:

答案 0 :(得分: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

我不确定这是否适用于您的情况,但我认为值得更多地使用路线。

答案 1 :(得分:0)

你可以用before_filter来做,但将STI模型分成不同的控制器并不是一个好方法。我完全同意下一个引用

  

这可能并不总是适用,但我还没有看到STI适用于多个控制器的情况。如果我们使用STI,我们的对象共享一组ID和属性,因此应该以基本相同的方式访问它们(按某些属性查找,按某些属性排序,限制管理员等)。如果演示文稿变化很大,我们可能希望从控制器渲染不同的模型特定视图。但是如果对象访问变化太多以至于建议单独的控制器,那么STI可能不是正确的设计选择。

点击http://code.alexreisner.com/articles/single-table-inheritance-in-rails.html