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 Bates,
#63 Model Name in URL - RailsCasts, it's very risky to
remove the id from the url...
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
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.
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.
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.
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.
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 ???