Removing User_ID from url params with Devise and FriendlyId gem

We have all our user profiles rendering through a handlebars template but as the attributes associated to the user grows, so does the loading time.

The only reason we have them loading through a handlebars template as opposed to a ruby template, is that the user_id is in the URL for devise/show.

Here is a quick guide to replicate how I solved that:



gem 'friendly_id', '~> 5.1.0'


rails generate friendly_id


I already have Devise set up for user authentication, so next I ran

rails g migration AddSlugToUser slug:string:uniq

Which produced this migration file:

class AddSlugToUser < ActiveRecord::Migration[5.0]
 def change
   add_column :users, :slug, :string
   add_index :users, :slug, unique: true


Mmmmkay – let’s migrate those goodies

rake db:migrate



I want the URL to use the first_name of the user. Many members might have the same first name, so I’m going to give the function a few options. The first option is to use just the first name. If that is taken, append a random number 1-10. If that is taken, append a random number 1-100, and then 1-1000.


class User < ApplicationRecord

  extend FriendlyId
  friendly_id :slug_candidates, use: :slugged

  def slug_candidates
      [:first_name, rand(1..10)],
      [:first_name, rand(1..100)],
      [:first_name, rand(1..1000)]



Now I ran in the console:


And I can see each user now has an attribute called slug, and it is their first_name, plus a unique number (or just first_name for the early birds!)


Adapt current setup

Currently, I have a profile controller, where each user can view their own profile


 get 'profile/:id', to: 'profile#view', as: 'view'

So, for the signed in user to view their profile, I changed the link to:

link_to main_app.view_path(current_user.slug)


Now, to render another user’s profile, running through an array of User records:

link_to image_tag(user.avatar.url(:medium)), main_app.view_path(user.slug)





Since I’m not requiring users to have a unique first_name, this will occasionally end up in a REALLY ugly url, such as:


because there are sooo many Walshs in the world.


The next step is to put the ability for a user to chose their own unique URL identifier, and save it in their settings. This will cut down on the chance that a unique name+number will be taken, when creating new users. I might write another blog post about this in the future, but for now it’s pretty straight forward in Friendly_id’s documentation


One interesting ‘gotcha’ I discovered later:


Started GET "/profile/queue" for ::1 at 2017-04-13 11:05:57 -0500

  Processing by ProfileController#view as HTML

  Parameters: {"id"=>"queue"}

Completed 401 Unauthorized in 1ms (ActiveRecord: 0.0ms)


Here, there was a route to a page called profile/queue. But now that the view is not profile/:id in a numeric, ActiveRecord id sense, it is looking for a slug called ‘queue’


Simple fix:

get 'profile/queue', to: 'profile#queue', as: 'queue'


get 'queue', to: 'profile#queue', as: 'queue'



PS. My roommate has a goldfish name Friendly, which is why the image for this post is a goldfish 🙂



Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s