Creating Pretty URLs From Multiple Attributes With friendly_id

by Mike Zazaian at 2009-10-04 22:42:27 UTC in plugins rails gems

a brief tutorial on how to make pretty urls for your Rails models using multiple attributes rather than one

6 comments 3 links

I wrote an article back in August about the wonderful friendly_id plugin and the utilities thereof. Long story short it became one of the more popular articles on the site (probably the most, really, as we didn't start tracking pageviews on the server side until early September) and I thought it might be useful to discuss how to extend its functionality a little bit.

some history

So friendly_id, for those of you too lazy to click on any of the above links, is a really nifty pretty-url plugin for Rails that provides you with a full library of methods for taking any given attribute on a Rails model and filtering that attribute to become the primary resource locator in lieu of the rails default, the record's id.

For example, if you wanted your article title URIs to use the article title rather than id, you'd do something like this:

#!/app/models/article.rb

has_friendly_id :title

Then, magically, and without explanation beyond the fact that the gods are benevolent and sometimes when we wish for things to happen they simply do, any time you find a record in the your Articles controller with Article.find(params[:id]) friendly_id will automatically interpret the url string and find the corresponding Article's id.

Take a look. In essence it's turning this:

http://www.mydomain.com/articles/33

Into this:

http://www.mydomain.com/articles/this-is-much-more-explanatory-and-seo-friendly

So that's the really basic version of what it does. And after I posted that initial article, a gentleman named Shaun posed a very interesting question, and one for which I didn't immediately have an answer.

I knew that if you wanted to customize the slugged field you could do so by passing that attribute into a block at the end of the has_friendly_id method call, like this:

#!/app/models/article.rb

has_friendly_id :title do |slug|
  slug.upcase! + "-my-pet-dromedary-is-ill"
end

Now, for whatever ungodly reason, your slugs will appear in all uppercase letters and indicate that your pet dromedary is ill. Cool, kind of.

But what Shaun wanted to do was to come up with a solution that integrated his created_at date into that block. Which I thought would be easy enough, something like:

#!/app/models/article.rb

has_friendly_id :title do |slug|
  slug + "-" + created_at.strftime('%Y-%m-%d')
end

Needless to say, I'm not very bright, and this didn't work because the created_at call, which was trying to read the created_at method on the Article model, was out of scope, because it was inside a block. Another needless statement would be to say that self.created_at didn't work either because again, I was calling it on a block.

So being the genius that I am, I put my faith in Shaun and let him come up with the solution on his own. And sure enough, he came through:

#!/app/models/article.rb

has_friendly_id :title_with_date

protected
def title_with_date
  title + "-" + created_at.strftime('%Y-%m-%d')
end

Neat, huh? In case you were wondering, the result looked something like this:

http://www.mydomain.com/a-really-seo-friendly-and-still-readable-url-2010-01-01

Cool, huh? Thanks for the help, Shaun. I get the feeling that this'll be useful to people.

update

Shaun strikes again. For anybody who read the article before, I referenced the use of Stringex to convert the title to a proper url format, but scholar that he is, Shaun recognized that it doesn't matter which attribute/value you pass into has_friendly_id, it will be converted to a proper format on the backend. Thanks again, Shaun. You're the man.

6 comments

Verdi Ergun at 2009-10-05 00:28:12 UTC

This is great!

Mike Zazaian at 2009-10-05 01:15:09 UTC

Glad you like it, Verdi -- I aims to please.

Shaun at 2009-10-05 20:41:00 UTC

Hey Mike,

Great write up! One comment/question - I don't think you need Stringex in this example, because friendly_id will add the dashes for you (make the slug), right?

It's just a matter of adding the dashes yourself with Stringex vs. using friendly_id to add the dashes, yeah?

Shaun

Mike Zazaian at 2009-10-05 23:33:47 UTC

Shaun! You're absolutely right! Good call. I'll post an update right away. Good eye -- and thanks again for the great contribution.

You should register a user account to keep track of your comments. At some point I'm going to be implementing a user karma system, and the comments will boost you up the active users list. Just a thought...

shaun at 2009-10-08 17:49:27 UTC

No problem^ and I signed up for an account too. ;)

Btw, does your rss feed work?

Shaun

Norman Clarke at 2009-11-06 17:04:31 UTC

Thanks for the writeup on friendly_id! I'm glad you find it useful.

post comment
Comments are marked down using Ryan Tomayko's excellent rdiscount gem, which follows standard markdown conventions. If you don't know markdown, you can learn it using the Daring Fireball markdown syntax guide.
required
required
login to post comments without entering your name, email address and recaptcha code each time, or register if you haven't already done so

markdown basics

**bold** __bold__ [link](http://link.com "link") * unordered list item
*italic* _italic_ ##h2 heading 1. ordered list item
> blockquote ####h4 heading <code>@ruby</code>

latest links

ActiveScaffold A Ruby on Rails plugin for dynamic, AJAX CRUD interfaces
rsl's stringex at master - GitHub Some [hopefully] useful extensions to Ruby’s String class. It is made up of three libraries: ActsAsUrl [permalink solution with better character translation], Unidecoder [Unicode to Ascii transliteration], and StringExtensions [miscellaneous helper methods for the String class].
friendly-id's friendly_id-2.1.4 Documentation

login

register activate reset

feeds

articles/rss

topics

staff

editor

about

doblock focuses on ruby, rails, and all things that can help ruby and/or rails programmers hone their skills.

Techniques, tutorials, news, and even free open-source applications, doblock seeks to fill in the cracks of the ruby/rails blogosphere.

doblock v. 0.8.22 powered by Rails