Nel fruscìo della pineta

User-friendly URLs in Ruby on Rails

Pubblicato da: VaLeRiO su: 28 gennaio 2009

Nel sito che presto pubblicherò mi sono ritrovato a dover gestire degli URL poco estetici e non adatti ai motori di ricerca.

Il sito tratta di vari paesi del mondo, con relativi menu e pagine.
Un paese (country) ha tanti menu e un menu ha tante pagine.
Un menu, appartiene soltanto ad un paese.
Una pagina, appartiene soltanto ad un menu.

Gli URL risultano sotto questa forma:

http://localhost:3000/country/x

Dove x è la chiave primaria (id) dello Stato (per esempio “Germania”, “Giappone”, …)

http://localhost:3000/menu/y

Dove y è la chiave primaria (id) del menu (per esempio “Territorio”, “Storia”, …)

http://localhost:3000/page/z

Dove z è la chiave primaria (id) della pagina (per esempio “Fiumi”, “Laghi”, …)

In questa maniera, la relazione tra paese, i suoi menu e le pagine và completamente persa in cambio di URL per niente chiari e molto “meccanici”.

Gli URL risultano così di default per la seguente proprietà in routes.rb

map.connect ‘:controller/:action/:id

Dove :controller è implicito (perchè stiamo già utilizzando quello di root), :action varia da “country” a “menu” o “page” e :id dipende dalla chiave primaria del record.

La soluzione del problema è semplice (se la si conosce xD). Aggiungere a routes.rb nuove proprietà (non anonime, per evitare di rallentare il framework):

map.show_country “/:country_name”, :controller => “home”, :action => “country”
map.show_menu “/:country_name/:menu_name”, :controller => “home”, :action => “menu”
map.show_page “/:country_name/:menu_name/:page_name”, :controller => “home”, :action => “page”

Dove il controller “home” è il controller di root, usato dal framework per passare da un paese all’altro o fra le varie pagine.

Nel controller “home” avremo:

def country
@country = Country.find_by_name(params[:country_name].capitalize)
end

def menu
@country = Country.find_by_name(params[:country_name].capitalize)
@menu = Menu.find_by_name(params[:menu_name].capitalize, :conditions => [ "country_id = ?", @country.id])
end

def page
@country = Country.find_by_name(params[:country_name].capitalize)
@menu = Menu.find_by_name(params[:menu_name].capitalize, :conditions => ["country_id = ?", @country.id])
@page = Page.find_by_name(params[:page_name].capitalize, :conditions => ["menu_id = ?", @menu.id])
end

Infine, nelle views, i paesi vanno così linkati:

link_to @country.name, show_country_path(:country_name => @country.name.downcase)

I menu:

link_to menu.name, show_menu_path(:country_name => @country.name.downcase, :menu_name => menu.name.downcase)

Le pagine:

link_to page.name, show_page_path(:country_name => @country.name.downcase, :menu_name => @menu.name.downcase, :page_name => page.name.downcase)

Gli URL risultanti saranno del tipo:


http://localhost:3000/germania/

http://localhost:3000/giappone/storia/

http://localhost:3000/germania/territorio/laghi


Direi decisamente meglio :P

Ultima nota: avrete sicuramente notato dei .downcase e dei .capitalize.
Questo perchè negli URL i nomi deveno essere minuscoli, ma nel database e nelle views sono maiuscoli.

Spero di essere stato d’aiuto :P
Buon Rails a tutti ;)

Lascia un Commento

Fill in your details below or click an icon to log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Log Out / Modifica )

Foto Twitter

You are commenting using your Twitter account. Log Out / Modifica )

Foto di Facebook

You are commenting using your Facebook account. Log Out / Modifica )

Connecting to %s

Follow

Get every new post delivered to your Inbox.