Slug generator

The Slug Generator is a utility component that installs a Model concern that can be used to generate a slug for a model.

You can see it in action in several components including the teams component, where it's used to generate a slug for a new Account.

Why use slugs?

Slugs are a nice alternative to exposing the ID of a record in the URL. They can also be more readable and SEO-friendly.

Slugs can be readable and SEO-friendly or they can be a random string of characters. The Slug Generator class provides both options.

Slugs are almost always used in the URLs of the records that they represent.

Installation

You typically won't need to directly install the Slug Generator component, since it will be automatically installed when you install the teams component and a few other components.

But in the rare case that you do need to install it directly, you can do so by running the following command:

Copy
rails g instrumental:callout

After installation, find the file app/models/concerns/slug_generator.rb and read the code to understand how it works (along with the info below).

Usage

To use the Slug Generator on a model. The following examples will show how to use the Slug Generator on an Account model (but you can use it on any model).

Note: These examples show exactly how the Account model that comes with the teams component is configured out of the box.

Copy
class Account < ApplicationRecord
  include SlugGenerator
end

Then you will typically want to generate a slug for the model when a new record is created. You can do this by adding a before_create callback to the model.

In this case, we're using the generate_random_slug method to generate a random string as the slug for the new record.

Copy
class Account < ApplicationRecord

# ... other code ...

  before_create :generate_slug

# ... other code ...

  private

  def generate_slug
    generate_random_slug
  end
end

Alternatively, you can use the generate_slug_by_name method to generate a slug for the model based on the name of the model.

Copy
def generate_slug
  generate_slug_by_name
end

Scoping uniqueness

Both the generate_random_slug and generate_slug_by_name methods have an optional scope_model parameter that can be used to scope the uniqueness of the slug.

If left nil, the slug will be globally unique, meaning that no other record with the same slug will exist in the database.

If you pass a model to the scope_model parameter, the slug will be scoped to that model. This is useful if you want to generate a slug for a model that is related to another model.

For example, let's say an Account has many Guitars.

Accounts should have a globally unique slug because there shouldn't be two accounts with the same slug, because that would result in duplicate URLs conflicts. You'd typically want to build account-based routes like domain.com/account-slug-a and domain.com/account-slug-b, and so on.

Guitars should have a slug that is unique within its' account. For example, "Account A" should not have two guitars with the slug "gibson-les-paul" because that would result in duplicate URLs conflicts. But both "Account A" and "Account B" should be able to have a guitar with the slug "gibson-les-paul", which would result in the URLs domain.com/account-a/gibson-les-paul and domain.com/account-b/gibson-les-paul.

Generating slugs based on a model attribute

When using the generate_slug_by_name method, you can (optionally) pass a model attribute using the slug_field parameter.

When slug_field is left nil, the generator will first try to use the attribute name (if it exists), then it will try title (if it exists), and as a last resort it will generate a random slug.

If you pass a model attribute, for example :brand, then the generator will use the value of the brand attribute to generate the slug.

In cases, you'll want to give users a field in the edit form for a model so that they can customize the slug.

Instrumental Components

I created Instrumental Components to make designing and building professional apps with Ruby on Rails easy, fast, and fun. I use it on all of my projects and I hope it helps you build something great.

Brian Casel
Brian Casel
Creator of Instrumental Components
Learn more Send me a question or request