How to create dynamic multiple routes


I’d like to create the menu that contains static item and dynamic item. Each item link to any specific page with specific url.

The menu :

* LISTINGS
   + Listings (link to: /news/listing)
   + Price (link to: /news/price)
   + Articles: Funny (link to: /news/funny)
   + Articles: Business (link to: /news/business)
   + Articles: Health (link to: /news/health)

All items on the menu collected from database. The static page (eg. Listings, Price) collected from pages table, and the others collected from articles table.

On the “LISTINGS” menu, Listings links to the static page (/news/listing). The others link to the show page of article (/news/:title). Admin have capability to edit the url (for static page). And for article page, it depends on the title of article (use permalink-fu plugin). It means, once the admin update the url, the routes must be change too.

Besides that I have the others routes:

/admin/login, /admin/articles (/admin/:controller), etc.

So, how to make all the routes run efficiently without creating conflict each others and how to make the routes change automatically when user do the change of url?

This is my solution :

First, we must consider the priority of the routes that we have. If we have two or more routes that handle the same incoming request, the first one will work and the others will be ignored.

Let’s create the routes for admin first.

map.login 'admin/login', ....
map.namespace :admin do |admin|
  admin.resources :articles
end

And then, we must create the route for menu. The static page have higher priority than article page. But, how do we distinguish the static page with the article page since they have the same routes. To solve it, I collect the the item pages from database which contains “/news”, then create routes for it. After that, I create route for article page.

pages = Page.all(:conditions => ["pages.params_1='news'"]) if ActiveRecord::Base.connection.tables.include?("pages")

unless pages.blank?
  permalinks = pages.collect(&:params_2)
  permalinks.delete("")

  permalinks.each do |permalink|
    map.connect "news/#{permalink}", :controller => "home", 
    :action => 'static_page', :params_1 => "news", :params_2 => "#{permalink}"
  end
end

map.show_article "news/:permalink", :controller => "articles", :action => "show"

One problem has solved. The other problem, how to make the route change automatically when the admin change url of the static page ?

Just create the observer model :

class PageObserver < ActiveRecord::Observer

  def reload_routes(page)
    ActionController::Routing::Routes.reload!
  end

  alias_method :after_save,    :reload_routes
  alias_method :after_destroy, :reload_routes
end

And don’t forget to edit config/environment.rb to load the observer :

config.active_record.observers = :page_observer

That’s all!

,

  1. #1 by Corey on January 2, 2015 - 4:50 pm

    You post interesting articles here. Your blog deserves much more visitors.
    It can go viral if you give it initial boost, i know
    very useful tool that can help you, just type
    in google: svetsern traffic tips

Leave a comment