Have STI classes:
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?
i.e.
user/1/page/2 is handled by: FirstTypePageController if "page 2" type is "FirstTypePage", and by SecondTypePageController if "page 2" type is "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.
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).
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
However, I'd suggest you to split the behavior on the view level only:
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
I'm not sure if that works in your case, but I think it is worth to play with routes more.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With