#63
Jul 27, 2007

Model Name in URL

By default, Rails uses the model's id in the URL. What if you want to use the name of the model instead? You can change this behavior by overriding the to_param method in the model. Watch this episode for details.
Download (10.8 MB, 6:07)
alternative download for iPod & Apple TV (7.9 MB, 6:07)
# product.rb
def to_param
  "#{id}-#{permalink}"
end

# controller
@product = Product.find(params[:id])

or

# product.rb
def to_param
  permalink
end

# controller
@product = Product.find_by_permalink(params[:id])

RSS Feed for Episode Comments 61 comments

1. chineseGuy Jul 27, 2007 at 00:34

nice!~


2. seb Jul 27, 2007 at 00:36

It will be great to use a before_filter fo @product = Product.find(params[:id]) to avoid duplicated lines.

Your screencast is a good example to show interest of using before_filter because you need to modify find to find_by_permalink in a bunch of actions instead of modifing one before_filter.

I don't know why rails generator do not generate this before_filter. (even in the views, it does not generate a _form partial but duplicates it in new and edit rhtml file) May be an idea for a new screencast if it's not already done :)

Thanks for this video!!


3. Skyblaze Jul 27, 2007 at 00:49

I didn't seen this screencast yet but anyway can't we change the "id" behaviour acting on routes.rb? It is only a route issue if the last part of the url goes in params[:id] we can change that by adding a new custom route.


4. Jimmie Jul 27, 2007 at 01:12

Nice!


5. bitbutter Jul 27, 2007 at 03:17

Just recently I made a plugin to do exactly this: http://www.bitbutter.com/seo_urls-plugin-making-show-pages-more-findable/14


6. Rich Jul 27, 2007 at 06:25

Does Rails automatically populate the permalink field? Most permalink implementations I've seen ask you to prepopulate the permalink column.


7. Rob Jul 27, 2007 at 07:20

Rich - you can use Rick Olson's permalink_fu plugin to automatically create permalinks for you. You'll want to use PermalinkFu.escape(...) in a before_save however instead of the automatic "has_permalink" as the latter doesn't update the permalink when you edit a model.


8. Ryan Bates Jul 27, 2007 at 08:38

@seb, good call. A before filter would work really well here, I should have mentioned it.

@Skyblaze, yes, you can add a custom route to do this as well. I don't know of an easy way to do this when using map.resources however.


9. Robert Evans Jul 27, 2007 at 10:04

I've writen a permalink plugin that extends String to allow permalizing of just about any type of string, including unicode.

http://svn.robertrevans.com/plugins/Permalize/
http://robertrevans.com/article/permalize-fun


10. Nicolás Sanguinetti Jul 27, 2007 at 19:48

Well, another approach would be to override the find method with something like:

@class Product
  def find(*args)
    return find_by_permalink(*args) if !args.first =~ /^\d+$/
    super
  end
end@

Or something similar, but You'd need to validate your product permalinks to not be all numbers, or else things can get messy. Still, could solve problems when you are adding this to an already existing app.

If you are doing this for a new app, then there shouldn't be much to worry about.

Oh, and of course, nothing beats having good tests to make sure no find method goes wild ;)


11. Oskar Lissheim-Boethius Jul 28, 2007 at 10:56

Great stuff, Ryan. It's really humbling the service you're doing to our community.

More, more, more RESTful stuff, please. This is the future.


12. Alek Jul 28, 2007 at 15:29

Hi Ryan:
Thanks for wonderful work that you are doing in the Rails community. I am just getting aquatinted with Rails and Ruby in general, and have completely gone nuts over the fact that it's wonderful to code in Rails and fun too! I think I am become a Rails addict!

I have been watching some of the most wonderful pod-cast on iTunes by you and have equally become and addict their too:-).

I have a question with regard to generating a view in which multiple controllers can be called into it. Instead of having only one model being displayed in the view, can I have multiple models, through one of the controllers, in one view? I am talking about the way one can generate a query in the database that then become another table. I am not sure if I am making sense, but very very much appreciate your response and a take on this.

Thanks so much,
Alek


13. Carl Jul 28, 2007 at 18:51

I had to do something like this for an admin page where people could see what employees had worked on on a specific day, but I needed to be able to use either an id number or username (it's an internal website for logging people's work), so I had the controller do a regex on the param. If it was all digits, then it must be an id, of it's not it must be a username. Of course I only had one controller I had to do that in, so it would probably not be a good idea in other areas.


14. Josh Peek Jul 29, 2007 at 07:15

Yet another plugin.

http://svn.joshpeek.com/projects/plugins/pseudo_primary_key


15. Josh Peek Jul 29, 2007 at 07:19

@seb

See Dan Manges post on Taking DRY Too Far

http://www.dcmanges.com/blog/36


16. Ryan Bates Jul 29, 2007 at 22:20

@Alek, I'm not entirely sure what you're asking. A controller can fetch as many models as it needs in one action/view. However, if you want to apply the technique showed in this episode, you will need a name to use in the URL. In that case the focus will be on one model, not on multiple models.


17. Alek Jul 31, 2007 at 10:26

Ryan:

Thanks very much for responding to my question. I am sorry that my question sounded somewhat confusing.

Here is what I really had in mind from the question I posed. Just as you would create queries within database, by merging tables into one entity, can you do the same in Rails?

Thanks Ryan,

Alek


18. Ryan Bates Jul 31, 2007 at 13:35

You can use the ":include" option in the find method to include multiple tables/models in one query.

If you're trying to make one model span multiple tables then I don't think that's possible without serious hacking.


19. Ismael Jul 31, 2007 at 15:30

Yet another permalink plugin!
This one raises RecordNotFound in case given permalink doesn't exist, so you can use it like #find and catch not found errors in rescue_action_in_public

http://code.estadobeta.com/plugins/sluggable_finder/README


20. Alek Aug 01, 2007 at 12:15

Thanks Ryan! Your info helps a lot. As for having one model spanning multiple tables, it is something I will not commit, even though it can be done, just because of "serious hacking" as you say. The :include option sounds perfect, however! Thanks again.


21. David Madden Sep 01, 2007 at 12:19

Thanks, a very simple solution.


22. Henrik N Oct 04, 2007 at 13:44

Note that you DON'T want to use "_" as the separator between the id and the permalink, if you rely on String#to_i. The screencast uses "-" which is fine.

If you use "_" and the permalink part begins with a number, you could get e.g. "123_456blah", and "123_456blah".to_i is 123456, not the expected 123. This is because "_" can be used in Ruby to make numbers more readable.


23. Mo Rashed Oct 27, 2007 at 09:47

Found this on the net:

You don't have to make a new field in your table, yu could just use this instead:

def to_param
    "#{id}-#{name.gsub(/[^a-z1-9]+/i, '-')}"
end

replace name with the field you want to slug/permalink.

What do you think Ryan?


24. Jaffet Nov 24, 2007 at 05:01

Im confused a little bit. I created new column in my db called permalink. Then i did like in the video, but my urls are /5-
no permalink string. I know the problem, i dont have anything in permalink. Is this permalink generated automatically from somewhere? Or do i have to do it manually, when i create new ex. article?


25. jaffet Dec 14, 2007 at 04:20

It works. But does this work with paginate plugin as well?


26. Stefano Dec 15, 2007 at 17:19

This has to be my favourite till now!
Thank you so much i really didn't know how to accomplish that (it is my first rails (and web development in general) project!)


27. Bala Dec 24, 2007 at 15:05

Mo Rashed: Thanks for the tip! I actually have :

  def to_param
    "#{id}-#{title.gsub(/[^a-z1-9]+/i, '-')}.html"
  end

Having .html makes it more search engine friendly.


28. cover Dec 26, 2007 at 13:55

Very cool, i think i've to change a lot of stuff. i've done a really bad thing (the permalink contains all the id-permalink stuff, and then i changed the routes.rb to use it instead of the id... a really bad thing :) )


29. steph Apr 06, 2008 at 11:07

great stuff...

now how would I format this route:

/users/156/items/6547

like this:

/john/items/6547


30. Tony Carrera May 16, 2008 at 10:46

This tutorial just saved me even MORE time. I was missing the def to_param in the user model. I was about to start messing with the routes, thankfully this is a much cleaner way to get this done.

Some of these things should be easier done. Oh well. Thank you!


31. scootertuning Oct 15, 2008 at 17:45

Thanks for this video :-)
Really nice and simple solution.


32. Gary Paulsen Jan 13, 2009 at 18:47

Perfect! Thanks for the information and tips! Hope to see more of your posts! Again Thanks!


33. Eric Mar 20, 2009 at 21:10

I thought for sure a permalink set as "1-epson-abcd-1234" would fail, but sure enough, to_i still converts it to 1.

I must admit I'm not entirely certain why or how, but it does. I will have to look into this.


34. Ryan Sandridge Aug 02, 2009 at 14:59

Any suggestions on how to allow permalink's with periods (".") in them? Assuming product is routed using "map.resources :products", then anything after a period will be treated as a format.


35. Nicolás Hock Dec 17, 2009 at 04:41

I have a small question. I've defined the "to_param" method but when I acess to /projects/1 (typing the URL) it doesn't change to /projects/1-name.

Here at railscasts it does changes the /episodes/63 to /episodes/63-name... how do you get that?


36. TripleThreat Dec 27, 2009 at 02:13

LOL @ Settlers of Catan... thats a fun game. You screencasts are invaluable!


37. Ben Holland Jan 03, 2010 at 19:08

Thank you! Once again you have saved my project from failure! I've learned 90% of my knowledge about rails from watching your screencasts. Please don't stop :)


38. kim Mar 12, 2010 at 07:44

Thanks for share!
Good post.
Kim from <a href="http://tweetomatic-profiteer-review.com/">tweetomatic profiteer</a>


39. Volker Mar 21, 2010 at 11:36

 Hi! Google gerade im Web und bin auf dieser Homepage gelandet.
Respekt, haben Sie toll gemacht.
Ich wünsche Ihnen weiterhin viel Erfolg mit Ihre Seite und natürlich viele Besucher.
Hier habe ich mich sehr wohl gefühlt und werde wieder hierher zurückkommen.
Freue mich auf einen Gegenbesuch auf meiner Homepage


40. Flower girl dress Apr 08, 2010 at 12:34

This is really fantastic


41. Deb May 08, 2010 at 07:34

Hi,

I second @Nicolás Hock question. How to redirect from /episodes/63 to /episodes/63-name.. in order to avoid caching duplicate pages.


42. john biryon May 30, 2010 at 03:19

nice post man. good to know modern name in url :)


43. dingo buliko May 30, 2010 at 03:20

thanks for the new knowledge!
check out my site as well if u want at: http://www.make-web-site.com/


44. Burst Generator May 31, 2010 at 19:21

I was very impressed with tutorials that you serve, feel very fortunate to be able to visit your site


45. online diploma Jun 02, 2010 at 03:58

Great informative post thanks for sharing.....


46. home school Jun 02, 2010 at 03:59

Amazing one, i appreciate this work....


47. Dior clothing Jun 05, 2010 at 01:03

那么,该通道的观点是完全正确的,您的资料是真正合理的家伙,你给我们提供了宝贵资料后,我完全同意楼上的观点。我经常浏览这个论坛上,当我米自由,我觉得有这么多的好资料,我们可以了解在这个论坛!www.notcredible.net


48. Bob Jun 05, 2010 at 10:48

I am still trying to learn and each one of these episodes is very helpful
Thank You


49. Eat Healthier Foods Jun 12, 2010 at 15:30

this is very informative.


50. Custom Logo Design Jun 23, 2010 at 06:44

That's working. Thanks..


51. tab Jul 06, 2010 at 23:27

<a href="http://www.signin.com">signin</a>
[URL= "http://www.googole.com"]google[/URL]
<a href=http://www.signin.com>signin</a>


52. Louis Vuitton Lodge GM Black M40052 Jul 16, 2010 at 08:01

nice !!!!!!


53. newark airport cab service Jul 22, 2010 at 11:18

Ruth, I am pleased to receive your comments - and I wish you well in your own blogging endeavours!


54. sweet memories of life Jul 22, 2010 at 11:19

thanks for sharing this information! it's very useful for a lot people try to understand how we can use this

product.


55. best seo services company Jul 22, 2010 at 11:20

I recently came across your blog and have been reading along. I thought I would leave my first

comment. I don't know what to say except that I have enjoyed reading. Nice blog. I will keep visiting this

blog very often.


56. best seo services Jul 24, 2010 at 10:40

Very usefull roadtrip tips… I have made some of the same mistakes they describe in the article and would have appreciated this article before I went off on my trip.


57. logo design service Jul 30, 2010 at 01:21

Worth sharing this information. Good Work


58. Arkadaslık sitesi Jul 31, 2010 at 05:33

Thanks You admin.


60. logo design Aug 04, 2010 at 18:29

thanks for sharing


63. <a href="http://www.beLasohbet.com" title="muhabbet" target="_blank">muhabbet</a> Aug 08, 2010 at 17:34

I found your blog on Yahoo and I just wanted to say that I think your writing is simply stunning! Thanks again for providing this content for free. <a href="http://www.beLasohbet.com" title="muhabbet" target="_blank">muhabbet</a>


64. free directory list Aug 11, 2010 at 22:20

If God would exists it will be you... very thanks for this screencast.


65. Arkadaslık sitesi Aug 15, 2010 at 06:43

Thanks You admin.


66. wariror Aug 18, 2010 at 21:52

hello thanks


67. Affordable Logo Design Aug 22, 2010 at 02:27

I try to learn each one of these episodes is very helpful especially for me Thank You so much for this great post


68. jordan retro shoes Aug 22, 2010 at 23:08

I always like it when I see another video available. Thanks for a great railscasts. I am really interested in this learning about this. , I feel strongly about information and love learning more on this. I would like to introduce this nice website to my friends.


69. reverse phone detective Aug 25, 2010 at 10:42

I didn't seen this screencast yet but anyway can't we change the "id" behaviour acting on routes.rb? It is only a route issue if the last part of the url goes in params[:id] we can change that by adding a new custom route.


70. louis vuitton shoes Aug 26, 2010 at 21:17

Thanks for sharing your article. I really enjoyed it. I put a link to my site to here so other people can read it. My readers have about the same interets


71. Cotton Yarn Manufacturer Aug 30, 2010 at 23:50

Good points in your post, you have a great blog here. Thanks for this information.


72. Flat Shoes Aug 31, 2010 at 00:31

I truly enjoyed this. It has been extremely informative as well as useful.thanks for sharing the information.


73. Motorcycle Clothing Aug 31, 2010 at 00:41

Its a very good post. I was very pleased to find this site. I wanted to thank you for this great read.


74. quality inspection china Aug 31, 2010 at 00:52

Thanks a lot for that a fantastically amazing post. such a very fine post.


75. snow boots Aug 31, 2010 at 01:05

I don't know of an easy way to do this when using map.resources however.


76. dell inspiron 6000 laptop battery Aug 31, 2010 at 01:20

Laptop accessories accept become one of the a lot of accepted cyberbanking things in the past. Laptops are the new face of advice and technology. Gradually demography the abode of desktop computers for the assorted advantages it offers. This is a laptop and can be acclimated about anywhere.


77. Love Poems Aug 31, 2010 at 03:46

The given article is quite interesting and it gave me very reliable and useful information.


78. louis vuitton sunglasses Sep 01, 2010 at 22:31

Nice post. My friend John told me about this blog some weeks ago but this is the first time I’m visting. I’ll undoubtedly be back.

Add your comment:

(SKIP THIS ONE)

(required)

(not shown)


(use pastie or gist for code)

sponsored by:
if you want to help:
required:
Get Quicktime Player
Give Back to Open Source