简体   繁体   English

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

[英]Rails Sti: single path, different controller

Have STI classes: 有STI课程:

class Page < ActiveRecord::Base
  belongs_to :user
end

class FirstTypePage < Page
end

class SecondTypePage < Page
end

Controllers for each class, 每个班级的控制器,

class PageController < AplicationCorroller
end

class FirstTypePageController < PageController
end

class SecondTypePageController < PageController
end

And routings: 和路线:

resources :user
  resource :page
end

How to handle FirstTypePage by FirstTypePageController, SecondTypePage by SecondTypePageController on single path? 如何通过FirstTypePageController处理FirstTypePage,SecondTypePage由单一路径上的SecondTypePageController处理?

ie

user/1/page/2 is handled by: FirstTypePageController if "page 2" type is "FirstTypePage", and by SecondTypePageController if "page 2" type is "SecondTypePage" ? user / 1 / page / 2由以下处理:FirstTypePageController如果“page 2”类型是“FirstTypePage”,则通过SecondTypePageController如果“page 2”类型是“SecondTypePage”?

UPDATE: My solution: 更新:我的解决方案:

  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

I think this solution will work fast on a small amount of page types, and we can manage memory size, used for routings on a large amount of pages 我认为这个解决方案可以在少量页面类型上快速运行,我们可以管理内存大小,用于大量页面上的路由

I can see one option to do that - preload all pages in the routes.rb and define special routes for each page. 我可以看到一个选项 - 在routes.rb中预加载所有页面并为每个页面定义特殊路由。

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

Another solution could be to use strategy patter in the PageController (no need to use FirstTypePageController and other). 另一种解决方案可能是在PageController使用策略模式(不需要使用FirstTypePageController和其他)。

pages_controller.rb: 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: 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

However, I'd suggest you to split the behavior on the view level only: 但是,我建议您仅在视图级别拆分行为:

show.html.haml: show.html.haml:

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

EDIT: 编辑:

I just found another solution, that could help you - custom constraints. 我刚刚找到了另一个解决方案,可以帮助你 - 自定义约束。 http://railsdispatch.com/posts/rails-3-makes-life-better http://railsdispatch.com/posts/rails-3-makes-life-better

I'm not sure if that works in your case, but I think it is worth to play with routes more. 我不确定这是否适用于您的情况,但我认为值得更多地使用路线。

you can do it with before_filter, but separating STI models into different controllers isn't good solution. 你可以用before_filter来做,但将STI模型分成不同的控制器并不是一个好的解决方案。 I totally agree with next quote 我完全同意下一个引用

This may not always apply, but I have yet to see a case where STI works well with multiple controllers. 这可能并不总是适用,但我还没有看到STI适用于多个控制器的情况。 If we are using STI, our objects share a set of IDs and attributes, and therefore should all be accessed in basically the same way (find by some attribute, sort by some attribute, restrict to administrators, etc). 如果我们使用STI,我们的对象共享一组ID和属性,因此应该以基本相同的方式访问它们(按某些属性查找,按某些属性排序,限制管理员等)。 If presentation varies greatly we may want to render different model-specific views from our controller. 如果演示文稿变化很大,我们可能希望从控制器渲染不同的模型特定视图。 But if object access varies so much that it suggests separate controllers, then STI may not have been the correct design choice. 但是如果对象访问变化太大以至于它建议单独的控制器,那么STI可能不是正确的设计选择。

took here http://code.alexreisner.com/articles/single-table-inheritance-in-rails.html 在这里http://code.alexreisner.com/articles/single-table-inheritance-in-rails.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM