0

On Rails 2.3.5

I have a view that public information about a user that lives at a URL like this:

http://www.mysite.com/users/johndoe

My route:

map.connect 'members/:id', :controller => "users", :action => "showmember"

I never want to expose the int IDs for users so I use the username as the id for that view.

When I link to it:

<%=link_to user.username, :controller => 'users', :action => 'showmember', :id => user.username %>

Everything is fine except if the username happens to include chars that need to be escaped. What's the best way to escape the id in link_to?

Nick
  • 8,483
  • 10
  • 46
  • 65

2 Answers2

1
CGI::escape(user.username)

that method will URI-encode the value so it's safe in the URL. Does Rails not do it automatically? Did you try not escaping and putting crazy characters in it?

Edit, and the opposite version:

CGI::unescape(params[:id])

Although I still feel like rails might handle it automatically for you. Might want to test.

Edit again:

Rails does have a .parameterize method so: user.username.parameterize will make a string url-friendly, it's documented here: http://apidock.com/rails/v3.0.7/String/parameterize

The main problem with this is that if you have 2 usernames: my.user and myuser they will both parameterize to the same string myuser

I think the accepted way of doing it is (as the doc example shows) like this:

"#{user.id}-#{user.username.parameterize}"

this way if you do User.find(params[:id]) it strips out everything after the first number and just uses that as the id. There are gems that will make a unique parameter-friendly string for you to use if you're really that against having the user id in the params (Is there a reason for this concern?). One such gem is friendly_id: https://github.com/norman/friendly_id/ although there are others. The idea is that there's another field on your model specifically for url's, and it's auto-generated on before_create based off of your username field. It has to be unique and parameter friendly, which the gem takes care of.

Hopefully this answer helps you out more :p

nzifnab
  • 15,876
  • 3
  • 50
  • 65
  • Hmm perhaps something else is going on. If the username has a . in it I get a Routing error. I thought this was due to it not being escaped but perhaps I was mistaken. ActionController::RoutingError (No route matches "/members/test.member" with {:method=>:get}): – Nick Jun 18 '11 at 18:28
  • I updated my post with a better solution. If you really don't want the id in the URL your best bet is probably a gem to generate the slug for you. – nzifnab Jun 18 '11 at 19:19
  • Thanks for all the awesome input this was a good read and informative even though I ended up adjusting the route based on this: http://stackoverflow.com/questions/5768326/rails-query-string-with-a-period. I obscure IDs because I don't want the number of users to be discernible. – Nick Jun 18 '11 at 19:31
0

The issue wasn't with escaping I ended up adjusting the route based on this question:

Rails query string with a period (or full stop).

Community
  • 1
  • 1
Nick
  • 8,483
  • 10
  • 46
  • 65