class Article < ApplicationRecord
before_validation :generate_slug, on: :create
validates :slug, presence: true, uniqueness: true
private
def generate_slug
return if slug.present?
words = title.parameterize.split("-")
self.slug = "#{words.first(2).join('-')}-#{SecureRandom.alphanumeric(4).downcase}"
end
end
class ArticlesController < ApplicationController
def show
@article = Article.find_by!(slug: params[:slug])
end
end
class AddSlugToArticles < ActiveRecord::Migration[7.0]
def change
add_column :articles, :slug, :string, null: false, unique: true
add_index :articles, :slug, unique: true
end
end
This snippet ensures every article gets a unique, readable slug
based on its title, keeping it short and pronounceable. It grabs the first two words of the title and appends a 4-character random string to prevent duplicates. The before_validation
callback runs only when creating a new article, and the controller fetches articles by slug instead of an ID—great for SEO!
Martin Sojka, Maker of CodeSnips