Learn to use pretty URLs in your Ruby on Rails web app.
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.
Change an id-based URL like this:
… to a more verbose URL like this:
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.
This is how to change the way that Rails finds records and routes to them:
- Create a method to generate the slug
- Add the slug to your records
- Override the to_param method in the models
- Specify you want the Rails routes to use the slug param.
- Update the find_by methods in your controllers to be find_by_slug
- Check out those verbose URLs in your browser!
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 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.
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
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_slug as a way of searching by a slug.
class PostController < ApplicationController def show @post = find_by_slug(params[:slug]) end end
Now when you visit pages in your webpage, you should see the slug describing the page.
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.
This article was originally published in freeCodeCamp at medium.freecodecamp.org.