Rails actions default on using record IDs. But what if we want to change the URL to something prettier, something that doesn’t leak the record ID in the database?
Luckily, there is a simple answer that doesn’t require you to change much. Let’s say we want to use a
slug in the URL for a
We start with the routes and the
# config/routes.rb Rails.application.routes.draw do ... resources :teams, param: :slug do member do get "another_route" end end
param option will change the paths from
/teams/:slug and allow us to use
params[:slug] in the controller. All paths generated with
resources will be changed.
At the controller level, we now have to look up records with this new alternative ID:
class TeamsController < ApplicationController before_action :set_team ... private def set_team # Instead of @team = Team.find!(params[:id]) @team = Team.find_by!(slug: params[:slug]) end end
Now things work, but we would need to change all
_url references to point to the new routes. However, these path helpers depend on
Model#to_param method which we can override with the new default:
class Team < ActiveRecord::Base ... def to_param slug end end
That’s it. Almost no work and we fixed our IDs-leaking URLs to something better. Don’t forget on the
slug index for a quick lookup.
← IT'S OUT NOW
I wrote a complete guide on web application deployment. Ruby with Puma, Python with Gunicorn, NGINX, PostgreSQL, Redis, networking, processes, systemd, backups, and all your usual suspects.