Reputation: 653
Is it a bad practice to leave the user's database id in the url like this:
localhost:3000/users/16/edit
If it is bad, how can I hide the id in the url? What do I have to watch out when calling the path in my view, routes.rb, etc?
If this is relevant to the discussion, the user resource looks like this in my routes.rb:
resources :users, only: [:new, :edit, :create, :update]
Upvotes: 3
Views: 437
Reputation: 290
Based on your route, it looks like your users will not have a publicly visible profile. If this is the case then you can simply use example.com/settings
for Users#edit and example.com/sign_up
for Users#new.
get 'settings', to: 'users#edit'
get 'sign_up', to: 'users#new'
resource :users, path: '', only: [:create, :update]
If your users will indeed have a publicly visible profile in the future, then you can either use the friendly_id gem as suggested by hawk or perhaps a randomized 7 digit ID by overwriting it before creating the record. After a bit of research, this is how I ended up doing it:
before_create :randomize_id
private
def randomize_id
self.id = loop do
random_id = SecureRandom.random_number(10_000_000)
break random_id unless random_id < 1_000_000 or User.where(id: random_id).exists?
end
end
Upvotes: 0
Reputation: 10856
While you can use friendly ids as described by hawk and RailsCast #314: Pretty URLs with FriendlyId, using the primary key in your routes is standard practice, maybe even best practice. Your primary key ensures the right record is being fetched whenever '/posts/1/edit' is being called. If you use a slug, you have to ensure uniqueness of this very slug yourself!
In your specific case it seems that you are building some kind of "Edit Profile" functionality. If each user is to edit only his or her own profile, you can route a Singular Resource.
Possible routes:
/profile # show profile
/profile/edit # edit profile
Then your user's primary key would not be visible from the URL. In all other models, I'd prefer to go with the id in the URL.
Upvotes: 1
Reputation: 5408
Simply override to_param
in ActiveRecord::Base subclass
class User < ActiveRecord::Base
validates_uniqueness_of :name
def to_param #overriden
name
end
end
Then query it like this
user = User.find_by_name('Phusion')
user_path(user) # => "/users/Phusion"
Alternatively you can use gem friendly_id
Upvotes: 3