Our task today is to add unique slugs to our Company model on our Ruby on Rails app. The Company model has name and location properties, and we want to use those to create the slug. E.g. the company named Lugo Labs and based in London should have a slug, lugo-labs-london. We can then use that when showing the company page.
We could create the solution ourselves, but today we'll use the awesome FriendlyId to help us with it.
Installing FriendlyId is easy, we add it to our Gemfile:
# Gemfile gem 'friendly_id'
In order to generate slugs for our existing Company records, we need to tell our FriendlyId when to generate the slugs, by adding this private method:
# apps/models/company.rb private def should_generate_new_friendly_id? slug.nil? || name_changed? || location_changed? end
We're telling FriendlyId to generate new slugs when the slug is
nil or name, or location attributes have changed.
Let's add a migration for adding the slug attribute (using Rails 5):
rails g migration add_slug_to_companies slug
We could also generate the slugs as part of the migration, if we had existing company records.
class AddSlugToCompanies < ActiveRecord::Migration[5.0] def up add_column :companies, :slug, :string add_index :companies, :slug, unique: true say_with_time 'generating company slugs' do Company.find_each(&:save) end end def down remove_column :companies, :slug, :string end end
save on the models triggers slug generation, so let's run the migration and see our slugs created:
We have also added a unique index on slug for good measure. FriendlyId also makes the slugs unique by default, appending a unique token to the next duplicated slug it finds. E.g. if we ever created another company Lugo Labs with location, London, its slug would be something like lugo-labs-london-127a893725532ahsr277.
In the Company model we add:
# apps/models/company.rb extend FriendlyId friendly_id %i(name location), use: :slugged
friendly_id macro has many options, here we're just telling it to use name and location to create slugs. You can see more info on this on the FriendlyId's README.
On the controller we can the enhancements provided by extending FriendlyId:
# app/controllers/companies_controller.rb class CompaniesController < ApplicationController def show @company = Company.friendly.find(params[:id]) end end
params[:id] is the company slug, rather than company id, the
friendly method makes the finder to look up companies by slug, rather than id.
Now when we create new Company records, they will have unique slugs generated automatically. The companies URLs are all pretty with words in them, rather than the ids.