Pretty URLs with gem friendly_id
1. Minimal setup - no additional column #
bundle add friendly_id
# will install the gem
#app/models/inbox.rb
extend FriendlyId
friendly_id :name
#app/controllers/inboxes_controller.rb
def set_inbox
-- @inbox = Inbox.find(params[:id])
++ @inbox = Inbox.friendly.find(params[:id])
end
2. :finders
- always add it! #
#app/models/inbox.rb
extend FriendlyId
-- friendly_id :name
++ friendly_id :name, use: [:finders]
#app/controllers/inboxes_controller.rb
def set_inbox
++ @inbox = Inbox.find(params[:id])
-- @inbox = Inbox.friendly.find(params[:id])
end
2. :slugged
- always add it too! #
rails g migration AddSlugToInboxes slug:uniq
# will add column that will store the friendly_id
#app/models/inbox.rb
extend FriendlyId
-- friendly_id :name, use: [:finders]
++ friendly_id :name, use: [:finders, :slugged]
Inbox.find_each(&:save)
# update the slug for all existing records
# in the above case, slug = name
- 2.1. you can create non-attribute slug names, like randoms
#app/models/inbox.rb
extend FriendlyId
-- friendly_id :name, use: [:finders, :slugged]
++ friendly_id :generate_random_slug, use: [:finders, :slugged]
++ def generate_random_slug
++ slug? ? slug : SecureRandom.uuid
++ end
- 2.2. candidates - use longer option if shorer one is taken
#app/models/inbox.rb
extend FriendlyId
-- friendly_id :name, use: [:finders, :slugged]
++ friendly_id :slug_candidates, use: [:finders, :slugged]
++ def slug_candidates
++ [
++ :name,
++ [:name, :description],
++ [:name, :descroption, :created_at]
++ ]
++ end
4. Conditionally auto-update slug #
#app/models/inbox.rb
extend FriendlyId
friendly_id :name
++ def should_generate_new_friendly_id?
++ name_changed?
++ end
NOTE: this can be a bit buggy:
- go to
edit
- change
name
to something invalid - submit, get normal validation error
- change
name
to something valid - submit, get
ActiveRecord::RecordNotFound (can't find record with friendly id: "ger"):
5. :history
. Customizing friendly_id.rb
#
All the new slugs will be saved in a separate database table -> you will be able to access records via their OLD URLs!
#app/models/inbox.rb
extend FriendlyId
-- friendly_id :name, use: [:finders, :slugged]
++ friendly_id :name, use: [:finders, :slugged, :history]
rails generate friendly_id
# create db/migrate/20211105220542_create_friendly_id_slugs.rb
# create config/initializers/friendly_id.rb
Did you like this article? Did it save you some time?