Automatically generates unique slugs for your Rails' model records, so you can expose SEO-friendly URLs.
Example:
https://myapp.com/products/big-red-backpack-321678
Where big-red-backpack-321678
is the slug.
slugifiable
can generate:
- Slugs like
"big-red-backpack"
or"big-red-backpack-321678"
: unique, string-based slugs based on any attribute, such asproduct.name
- Slugs like
"d4735e3a265"
: unique hex string slugs - Slugs like
321678
: unique number-only slugs
When building Rails apps, we usually need to expose something in the URL to identify a record, like:
https://myapp.com/products/123
But exposing IDs (like 123
) is not usually good practice. It's not SEO-friendly, it can give away how many records you have in the database, it could also be an attack vector, and it just feels off.
It would be much better to have a random-like string or number instead, while still remaining unique and identifiable:
https://myapp.com/products/d4735e3a265
Or better yet, use other instance attribute (like product.name
) to build the slug:
https://myapp.com/products/big-red-backpack
slugifiable
takes care of building all these kinds of slugs for you.
Add this line to your application's Gemfile:
gem 'slugifiable'
Then run bundle install
.
After installing the gem, add include Slugifiable::Model
to any ActiveRecord model, like this:
class Product < ApplicationRecord
include Slugifiable::Model # Adding this provides all the required slug-related methods to your model
end
That's it!
Then you can, for example, get the slug for a product like this:
Product.first.slug
=> "4e07408562b"
You can also define how to generate slugs:
class Product < ApplicationRecord
include Slugifiable::Model
generate_slug_based_on :name
end
And this will generate slugs based on your Product
instance name
, like:
Product.first.slug
=> "big-red-backpack"
If your model has a slug
attribute in the database, slugifiable
will automatically generate a slug for that model upon instance creation, and save it to the DB.
Important
Your slug
attribute SHOULD NOT have null: false
in the migration / database. If it does, slugifiable
will not be able to save the slug to the database, and will raise an error like ERROR: null value in column "slug" of relation "posts" violates not-null constraint (PG::NotNullViolation)
This is because records are created without a slug, and the slug is generated later.
If you're generating slugs based off the model id
, you can also set a desired length:
class Product < ApplicationRecord
include Slugifiable::Model
generate_slug_based_on :id, length: 6
end
Which would return something like:
Product.first.slug
=> "6b86b2"
More details in the "How to use" section.
Slugs should never change, so it's recommended you save your slugs to the database.
Therefore, all models that include Slugifiable::Model
should have a slug
attribute that persists the slug in the database. If your model doesn't have a slug
attribute yet, just run:
rails g migration addSlugTo<MODEL_NAME> slug:text
where <MODEL_NAME>
is your model name in plural, and then run:
rails db:migrate
And your model should now have a slug
attribute in the database.
When a model has a slug
attribute, slugifiable
automatically generates a slug for that model upon instance creation, and saves it to the DB.
slugifiable
can also work without persisting slugs to the databse, though: you can always run .slug
, and that will give you a valid, unique slug for your record.
By default, when you include Slugifiable::Model
, slugs will be generated as a random-looking string based off the record id
(SHA hash)
slugifiable
supports both id
and uuid
.
The default setting is:
generate_slug_based_on id: :hex_string
Which returns slugs like: d4735e3a265
If you don't like hex strings, you can get number-only slugs with:
generate_slug_based_on id: :number
Which will return slugs like: 321678
β nonconsecutive, nonincremental, not a total count.
When you're generating obfuscated slugs (based on id
), you can specify a desired slug length:
generate_slug_based_on id: :number, length: 3
The length should be a positive number between 1 and 64.
If instead of obfuscated slugs you want human-readable slugs, you can specify an attribute to base your slugs off of. For example:
generate_slug_based_on :name
Will look for a name
attribute in your instance, and use its value to generate the slug. So if you have a product like:
Product.first.name
=> "Big Red Backpack"
then the slug will be computed as:
Product.first.slug
=> "big-red-backpack"
There may be collisions if two records share the same name β but slugs should be unique! To resolve this, when this happens, slugifiable
will append a unique string at the end to make the slug unique:
Product.first.slug
=> "big-red-backpack-321678"
After checking out the repo, run bin/setup
to install dependencies. Then, run rake spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
.
Bug reports and pull requests are welcome on GitHub at https://github.com/rameerez/slugifiable. Our code of conduct is: just be nice and make your mom proud of what you do and post online.
The gem is available as open source under the terms of the MIT License.