ruby 34 lines · 7 steps

How a Rails model builds unique slugs

A Post generates a URL-friendly, collision-free slug before validation and exposes it as the route param.

Explained by highlit
1class Post < ApplicationRecord
2 before_validation :generate_slug, on: :create
3 
4 validates :slug, presence: true, uniqueness: true
5 
6 def to_param
7 slug
8 end
9 
10 private
11 
12 def generate_slug
13 return if title.blank?
14 
15 base = normalize(title)
16 candidate = base
17 suffix = 2
18 
19 while self.class.where.not(id: id).exists?(slug: candidate)
20 candidate = "#{base}-#{suffix}"
21 suffix += 1
22 end
23 
24 self.slug = candidate
25 end
26 
27 def normalize(string)
28 I18n.transliterate(string)
29 .downcase
30 .gsub(/[^a-z0-9\s-]/, "")
31 .strip
32 .gsub(/[\s-]+/, "-")
33 end
34end
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1A before_validation callback lets you populate derived fields before the same record's validations run.
  2. 2Probing the database for existing values and appending a counter guarantees uniqueness without raising errors.
  3. 3Overriding to_param swaps the integer id for a human-readable slug in generated URLs.

Related explainers

Share this explainer

Here's the card — post it anywhere.

How a Rails model builds unique slugs — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code