User Permalink in Rails?


#1

Hey guys,

How do we create Permalinks for users in a Rails application ???
By Permalink a mean the name of the user in the URL like so:
example.com/username… Or like twitter and everyone does it ex:
twitter.com/username

I checked everywhere for that and didnt find a relevant answer…
I think it has something to do with overriding the to_param method in
the User model… but according to this screencast from Ryan B.,
http://railscasts.com/episodes/63-model-name-in-url, it’s very risky to
remove the id from the url…

Is there a way to do it ??? I suppose there is…

Thx for your help…

Louis-Pierre


#2

You could just do that for the show method. Depending on your
situation.
If you were to pass the username in the query string just use a method
like
this:

def show
@user = User.find_by_username(params[:id])
end

-Chris

On Sun, Jan 25, 2009 at 2:21 PM, Louis-Pierre D. <


#3

Well, I haven’t watched the screencast, but can’t really imagine how
“harmful” that could be.

The first thing you would need to do is use the permalink_fu plugin ->
http://github.com/technoweenie/permalink_fu/tree/master

And then you could override the “find” method in your model to a
finder like this one:

def find( *args )

  if args.first.kind_of?( String ) and !args.first.kind_of?(

Symbol ) and (args.first !~ /^[0-9]/ || args.first.include?(’-’))
if args.size == 1
super :first, :conditions => { permalink_field => args.first }
else
with_scope :find => { :conditions => { permalink_field =>
args.first } } do
args[ 0 ] = :first
super( *args )
end
end
else
super( *args )
end

end

What would assure that if a number is passed, it would use the good
old finder, but if it’s not a number, it will try to find using the
permalink_field. This has solved my needs, maybe it can solve yours
too.

Maurício Linhares
http://alinhavado.wordpress.com/ (pt-br) | http://blog.codevader.com/
(en)

On Sun, Jan 25, 2009 at 5:21 PM, Louis-Pierre D.


#4

Ok… I’ll try that then… Thx a lot for helping…

Louis-Pierre


#5

You don’t need to do self.username, just username will suffice

On 26/01/2009, at 20:42, MatthewRudy removed_email_address@domain.invalid


#6

On Jan 25, 9:22 pm, Chris J. removed_email_address@domain.invalid wrote:

You could just do that for the show method. Depending on your situation.
If you were to pass the username in the query string just use a method like
this:

def show
@user = User.find_by_username(params[:id])
end

-Chris

I think this is the right approach

take a look at the rails docs on to_param.
http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M002024

So the right solution is

map.resources :users

class User
def to_param
self.username
end
end

class UsersControllers
def show
@user = User.find_by_username(params[:id])
end

def something_that_redirects
redirect_to users_path(@user)
end
end

Should suffice,
and is much better practice than overwriting the “find” method.

Enjoy.

Matthew R.


#7

And if you DO use to_param and do something like this:

def to_param
“#{id}-#{name}”
end

And then go to the URL such as /users/15-Radar

In that show action you can then do:

User.find(params[:id])

still, and get the user. This is because the find calls to_i on the
string that is passed into it, so it is equivalent to doing
User.find(15).


Ryan B.
Mocra - Premier iPhone and Ruby on Rails Consultants
w - http://mocra.com
e - removed_email_address@domain.invalid
p - +61 432 937 289 or +61 7 3102 3237
skype - radarlistener


#8

Brian H. wrote:

LOL
There’s no reason to use to_param. It’s just a convention to pass the
id through the URL. It’s type is not enforced.

expects /users/15

def edit
@user = User.find(params[:id])
end

expects /users/bphogan

def show
@user = User.find_by_username(params[:id])
end

The only thing to watch out for is that find throws a RecordNotFound
exception when there is no record found, which will display a 404 in
production, and find_by_username returns nil, so you’ll wanna handle
that.

But there’s no need to do anything funny with to_params or routing or
anything like that.

Thx a lot but I really do want to get rid of the /user before “username”
so my url looks like this: http://mydomain.com/username… like i said
before…
http://twitter.com/gigaom for instance… How do i get rid of “user/” in
the url ???

thx again


#9

LOL
There’s no reason to use to_param. It’s just a convention to pass the
id through the URL. It’s type is not enforced.

expects /users/15

def edit
@user = User.find(params[:id])
end

expects /users/bphogan

def show
@user = User.find_by_username(params[:id])
end

The only thing to watch out for is that find throws a RecordNotFound
exception when there is no record found, which will display a 404 in
production, and find_by_username returns nil, so you’ll wanna handle
that.

But there’s no need to do anything funny with to_params or routing or
anything like that.


#10

map.connect ‘:username’, :controller => “users” , :action => “show”

At the bottom of your routes.rb file.

Ryan B.


#11

If you do

map.connect ‘:username’, :controller => “users” , :action => “show”

you’ll need to look for params[:username] instead of params[:id] when
you look up the record.