FriendlyId Documentation

repository·master·Indexed 27 days ago

https://github.com/norman/friendly_id

A 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.

Tokens
3.7K
Snippets
16
Records
24
Agent score
91%

What's inside FriendlyId

  1. Restore FriendlyId 4.0 style finders in Version 5.0+

    master
    In FriendlyId 5.0 and later, finders are no longer overridden by default. To use Model.find('slug') instead of the required Model.friendly.find('slug'), you must include the :finders addon in your friendly_id declaration.
  2. Install and Setup FriendlyId

    master

    To integrate FriendlyId into your Rails application, follow these steps:

    1. Add the gem to your Gemfile (ensure you use version 5.0.0 or greater for Rails 4.0+):
      gem 'friendly_id', '~> 5.5.0'
    2. Run bundle install.
    3. Generate a migration to add a slug column to your target table (e.g., Users):
      rails g migration AddSlugToUsers slug:uniq
    4. Generate the FriendlyId configuration file and migrations:
      rails generate friendly_id
      Note: You can delete the CreateFriendlyIdSlugs migration if you do not intend to use the slug history feature.
    5. Run the migrations:
      rails db:migrate
    gem 'friendly_id', '~> 5.5.0'
  3. Regenerate slugs in Version 5.0+

    master

    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-diner
  4. Migrate from FriendlyId 4.0 to 5.0+

    master

    To upgrade from version 4.0, follow these steps:

    1. Run the generator to create a configuration initializer: rails generate friendly_id --skip-migration
    2. Edit config/initializers/friendly_id.rb to adjust settings and restore any 4.0 defaults you require.
    3. If you plan to use the :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: true
  5. Find records using FriendlyId slugs

    master

    When 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
    end
  6. Configure a Model to use FriendlyId

    master

    To 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
    end
  7. Find records by locale using SimpleI18n

    master

    The 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")
    end
  8. Configure database columns for SimpleI18n

    master

    When 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
    end
  9. Enable slug history to avoid 404s

    master

    The 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.

    Setup

    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:migrate

    This creates the friendly_id_slugs table used by the FriendlyId::Slug model.

    Usage

    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
    end

    Handling Redirects

    When 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
    end
    class Post < ActiveRecord::Base
      extend FriendlyId
      friendly_id :title, :use => :history
    end
  10. Translate slugs using SimpleI18n

    master

    The 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")
    end
  11. Enable FriendlyId in an ActiveRecord model

    master

    To 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")
  12. Set global defaults for FriendlyId

    master

    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