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.
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.
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:
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).
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.
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.
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.
def generate_slug
generate_slug_by_name
end
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
.
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.
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.