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)
enddef menu
@country = Country.find_by_name(params[:country_name].capitalize)
@menu = Menu.find_by_name(params[:menu_name].capitalize, :conditions => [ "country_id = ?", @country.id])
enddef 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
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 ![]()
Buon Rails a tutti