A Ruby on Rails guide to creating user-friendly URLs with slugs instead of record IDs.
When you browse the web, you usually see URLs that are descriptive of the page you are going to. For example Medium’s blog post URLs are formed by the title of the post. Using Ruby on Rails resources for your routing defaults to finding models by their ids. This post will show you how to change this to route and find a model’s URL.
- What are pretty URLs?
- Generate the pretty URL strings
- Add slugs to your records
- Override to_param
- Set routes to use slugs
- Find by slugs in your controllers
- Enjoy the pretty URLs
- Find out more
What are pretty URLs?
A slug is a name given to a URL of a page, which derives from the publishing and printing industries. There is no single best way of routing on websites. Some use full words and sentences, some use an id, some use a combination of both. For example, Medium puts the id at the end of the URL slug.
In this article you will learn to change an id-based URL like this:
… to a more verbose URL like this:
Generate the pretty URL strings
It’s useful to have a method to use across your app to ensure that URLs are formatted the same way and won’t have issues when browsers try to display them. One way to do this is by including it in your base record class:
# app/models/application_record.rb module ApplicationRecord def to_slug(string) string.parameterize.truncate(80, omission: '') end end
Add slugs to your records
Add the field to your records by first running a migration:
rails generate migration AddSlugToPost slug:string rails rake db:migrate
Then ensure that the create and update include the slug field.
If you’ve already created records, you can run a task to add the slugs in, such as the following (assuming you want a slug based on a name field).
class Post < ApplicationRecord def self.add_slugs update(slug: to_slug(name)) end end
Then in the terminal, run:
rails console Post.add_slugs
Rails’ default to_param method returns the id of the record. If you override this, then when you add a record to a view, such as…
<%= link_to "View post", @post %>
… it will route to post/my-post-url-slug rather than the id, for example
class Post < ApplicationRecord def to_param slug end end
Performance issues: Computers find searching by ids quicker than strings, so there may be a performance impact of using the slug to find the records. There are alternative options, such as Stack Overflow, including the id then the slug after that.
Set routes to use slugs
Next up is updating config/routes.rb in your Rails project. The resources helper methods will by default use id. You can override this by telling it to use slugs instead.
resources :post, param: :slug
Find by slugs in your controllers
Almost there… Lastly, you need to tell your controllers to find records by slug rather than id. Rails will interpret the field you specify in the name of a find_by method, so you can use
find_by as a way of searching by a slug.
class PostController < ApplicationController def show @post = find_by(slug: params[:slug]) end end
Enjoy the pretty URLs
Now when you visit pages in your webpage, you should see the slug describing the page.
Find out more
Learning how to configure and define pretty URLs can make it easier to discover and navigate content on your website.
The Ruby on Rails Guides are a good place to learn more about routing and URLs, and my other Ruby on Rails posts cover other areas of this web app framework.