By default in Rails, a resource has a URL that indicates what kind of resource it is, and what its id number is. So you might have a website with information about bands, and the URL www.music.com/bands/123 might refer to the Rolling Stones.
For lots of reasons it'd be preferable to be able to have www.music.com/bands/the-rolling-stones instead. Here's a straightforward way to do this - but note, as things stand it will break any incoming links you might have.
The basic idea is that rather than retrieving a record based on its id, we retrieve records based on another field that corresponds to the desired URL. We'll call this field munged_name.
So first we need to create the following migration
class AddMungedNameToBands < ActiveRecord::Migration
def self.up
add_column 'bands', 'munged_name', :string
end
def self.down
remove_column 'bands', 'munged_name'
end
end
Then, to the Band model, add
def to_param
name.gsub(/\s/, "-").gsub(/[^\w&-]/,'').downcase
end
With Rails, every object has a to_param method. By default, ActiveRecord objects return the object's id. Here, we override that with a method that returns the band's name, with any spaces replaced with dashes (the first regexp), any punctuation stripped out (the second regexp), and converted to lower case. This is apparently known as munging. So now, applying the to_param method to a Band object returns the munged form of the band's name
Also to the Band model, add
def calculate_munged_name
self.munged_name = to_param
end
This sets the munged_name field and will be called after record has been created.
To the create and update methods of the bands controller, add
@band.calculate_munged_name
just after @band has been set
Given that we already have records in our database we need to give them munged names, so at the console do
>> Band.find(:all).each do |b|
b.calculate_munged_name
b.save
end
Finally, in the show, edit, update, and destroy methods of the bands controller, change
@band = Band.find(params[:id]
to
@band = Band.find_by_munged_name(params[:id])
Friday, January 30, 2009
Subscribe to:
Comments (Atom)