Restore FriendlyId 4.0 style finders in Version 5.0+
masterModel.find('slug') instead of the required Model.friendly.find('slug'), you must include the :finders addon in your friendly_id declaration.repository·master·Indexed 27 days ago
https://github.com/norman/friendly_idA plugin for Active Record that enables the use of human-friendly slugs (permalinks) in URLs instead of numeric IDs. It provides features such as slug history to prevent 404s, i18n support via the SimpleI18n module, and scoped slugs. The library includes tools for configuring slug candidates, managing global defaults, and performing slug-based lookups using Model.friendly.find.
Model.find('slug') instead of the required Model.friendly.find('slug'), you must include the :finders addon in your friendly_id declaration.To integrate FriendlyId into your Rails application, follow these steps:
Gemfile (ensure you use version 5.0.0 or greater for Rails 4.0+):gem 'friendly_id', '~> 5.5.0'bundle install.slug column to your target table (e.g., Users):rails g migration AddSlugToUsers slug:uniqrails generate friendly_idNote: You can delete the CreateFriendlyIdSlugs migration if you do not intend to use the slug history feature.rails db:migrategem 'friendly_id', '~> 5.5.0'In Version 5.0 and later, slugs are no longer automatically regenerated when a record is saved. To force a regeneration, you must explicitly set the slug column to nil and save the record. Alternatively, you can override the should_generate_new_friendly_id? method to restore automatic regeneration.
restaurant.friendly_id # joes-diner
restaurant.name = "The Plaza Diner"
restaurant.save!
restaurant.friendly_id # joes-diner
# To regenerate:
restaurant.slug = nil
restaurant.save!
restaurant.friendly_id # the-plaza-dinerTo upgrade from version 4.0, follow these steps:
rails generate friendly_id --skip-migrationconfig/initializers/friendly_id.rb to adjust settings and restore any 4.0 defaults you require.:history and :scoped addons together, you must update your friendly_id_slugs table to include a :scope column and update your unique index.# Migration for using :history and :scoped addons together
add_column :friendly_id_slugs, :scope, :string
remove_index :friendly_id_slugs, [:slug, :sluggable_type]
add_index :friendly_id_slugs, [:slug, :sluggable_type]
add_index :friendly_id_slugs, [:slug, :sluggable_type, :scope], unique: trueWhen retrieving records via slugs in a controller, replace the standard Model.find call with Model.friendly.find. This allows the application to resolve the human-friendly string instead of a numeric ID.
Example usage in a controller:
class UserController < ApplicationController
def show
@user = User.friendly.find(params[:id])
end
endTo enable slugging on a model, extend FriendlyId and call the friendly_id method specifying the attribute to use for the slug and the module to use (e.g., :slugged).
Example for a User model using the name attribute:
class User < ApplicationRecord
extend FriendlyId
friendly_id :name, use: :slugged
endThe find method in SimpleI18n automatically respects the current I18n.locale. To find a record using a specific locale's slug, wrap the call in I18n.with_locale.
# Find using current locale
I18n.locale = :es
Post.friendly.find("la-guerra-de-las-galaxias")
# Find using an explicit locale
I18n.with_locale(:es) do
Post.friendly.find("la-guerra-de-las-galaxias")
endWhen using SimpleI18n, your database table must include a slug column for every locale you support. By default, FriendlyId looks for columns named using the pattern [base_slug_name]_[locale].
For example, if your base slug column is slug, the columns should be slug_en, slug_es, slug_pt_br, etc. You can customize the base name by passing the :slug_column option in your FriendlyId configuration. Note that the column for the default locale must also include the locale suffix in its name.
# Example migration for a Post model
def self.up
create_table :posts do |t|
t.string :title
t.string :slug_en
t.string :slug_es
t.string :slug_pt_br
t.text :body
end
add_index :posts, :slug_en
add_index :posts, :slug_es
add_index :posts, :slug_pt_br
endThe FriendlyId::History module allows you to store a log of a model's previous slugs. This ensures that when a slug changes, you can still perform finds using the old ID, preventing broken URLs.
You must add a table to your database schema to store the slug records. Use the provided FriendlyId generator:
rails generate friendly_id
rake db:migrateThis creates the friendly_id_slugs table used by the FriendlyId::Slug model.
To enable history on a model, use the :history option in your friendly_id configuration:
class Post < ActiveRecord::Base
extend FriendlyId
friendly_id :title, :use => :history
endWhen finding a record by a friendly ID, the requested slug might not match the current slug if the record was previously updated. To avoid SEO issues and broken links, you should perform a 301 redirect to the current path:
class PostsController < ApplicationController
before_filter :find_post
def find_post
@post = Post.friendly.find params[:id]
# If an old id was used, redirect to the new current slug
if params[:id] != @post.slug
return redirect_to @post, :status => :moved_permanently
end
end
endclass Post < ActiveRecord::Base
extend FriendlyId
friendly_id :title, :use => :history
endThe FriendlyId::SimpleI18n module provides basic internationalization support for slugs. It requires your model to have a separate slug column for each locale (e.g., slug_en, slug_es).
To translate or set an existing record's friendly ID for a specific locale, use the set_friendly_id method. This method ensures the text is properly escaped, transliterated, and sequenced. If no locale is provided, it uses the current I18n.locale.
# Set slug for a specific locale
post.set_friendly_id("La guerra de las galaxias", :es)
# Set slug using the current I18n.locale
I18n.with_locale(:es) do
post.set_friendly_id("La guerra de las galaxias")
endTo use FriendlyId in an ActiveRecord model, you can either extend FriendlyId or include FriendlyId. This adds the friendly_id class method and enables slug-based lookups. Once enabled, you can find records using slugs via the friendly.find method, similar to how you use standard numeric IDs.
Example usage:
# Standard find
Person.find(82542335)
# Slug-based find
Person.friendly.find("joe")Person.friendly.find("joe")You can define global configuration defaults that will be applied to every model that uses FriendlyId. By default, FriendlyId only uses the :reserved module. Use FriendlyId.defaults to pass a block that configures the config object.
Common configuration methods within the block include config.base to specify the attribute used for slugs and config.use to enable specific modules like :slugged or :reserved.
FriendlyId.defaults do |config|
config.base :name
config.use :slugged
end