Sluggable Rails 🏅
Provide a unique slug to your records, generated from the attribute of your choice.
Usage
Use the has_slug
method:
# == Schema Information
#
# Table name: Post
#
# id :integer not null, primary key
# title :string
# slug :string not null
# created_at :datetime not null
# updated_at :datetime not null
#
class Post < ApplicationRecord
#...
has_slug by: :title
#...
end
post = Post.create title: 'My first slugified post!'
post.slug # "my-first-slugified-post"
another_post = Post.create title: 'My first slugified post!'
another_post.slug # "my-first-slugified-post-1"
In this example, the slug will be generated from the post title. By default, it will be stored in the slug attribute. You can choose another attribute to store it:
class Post < ApplicationRecord
#...
has_slug :custom_attribute, by: :title
#...
end
The slug is generated with the parameterize
method, you can specify a separator as it expects (default: '-'
):
class Post < ApplicationRecord
#...
has_slug :custom_attribute, by: :title, separator: '_'
#...
Obviously, you have to add the corresponding column to your schema:
class CreatePosts < ActiveRecord::Migration[5.1]
def change
create_table :posts do |t|
t.string :title
t.string :slug, null: false, index: true, unique: true # Or your custom attribute
t.timestamps
end
end
end
The slug will be automatically generated in order to be unique. And a presence
and uniqueness
validations will also be added by the has_slug
method.
Moreover, you can define a scope for your slug so its uniqueness will depend on other attributes:
class Post < ApplicationRecord
#...
belongs_to :user
has_slug by: :title, scope: :user_id
# You can specify more than one attribute by giving an array of attributes to the scope option.
#...
end
In this example, each post will have a slug which is unique for the user it belongs to (but it could be any other attribute).
The corresponding migration would be:
class CreatePosts < ActiveRecord::Migration[5.1]
def change
create_table :posts do |t|
t.string :title
t.references :user, foreign_key: true
t.string :slug, null: false
t.timestamps
end
add_index :posts, [:user_id, :slug], unique: true
end
end
Installation
Add this line to your application's Gemfile:
gem 'sluggable-rails'
And then execute:
$ bundle
Or install it yourself as:
$ gem install sluggable-rails
License
The gem is available as open source under the terms of the MIT License.