Module: FriendlyId::Base

Defined in:
lib/friendly_id/base.rb

Overview

Setting Up FriendlyId in Your Model

To use FriendlyId in your ActiveRecord models, you must first either extend or include the FriendlyId module (it makes no difference), then invoke the friendly_id method to configure your desired options:

class Foo < ActiveRecord::Base
  include FriendlyId
  friendly_id :bar, :use => [:slugged, :simple_i18n]
end

The most important option is :use, which you use to tell FriendlyId which addons it should use. See the documentation for this method for a list of all available addons, or skim through the rest of the docs to get a high-level overview.

A note about single table inheritance (STI): you must extend FriendlyId in all classes that participate in STI, both your parent classes and their children.

The Default Setup: Simple Models

The simplest way to use FriendlyId is with a model that has a uniquely indexed column with no spaces or special characters, and that is seldom or never updated. The most common example of this is a user name:

class User < ActiveRecord::Base
  extend FriendlyId
  friendly_id :login
  validates_format_of :login, :with => /\A[a-z0-9]+\z/i
end

@user = User.friendly.find "joe"   # the old User.find(1) still works, too
@user.to_param                     # returns "joe"
redirect_to @user                  # the URL will be /users/joe

In this case, FriendlyId assumes you want to use the column as-is; it will never modify the value of the column, and your application should ensure that the value is unique and admissible in a URL:

class City < ActiveRecord::Base
  extend FriendlyId
  friendly_id :name
end

@city.friendly.find "Viña del Mar"
redirect_to @city # the URL will be /cities/Viña%20del%20Mar

Writing the code to process an arbitrary string into a good identifier for use in a URL can be repetitive and surprisingly tricky, so for this reason it's often better and easier to use slugs.

Instance Method Summary (collapse)

Instance Method Details

- (Object) friendly

Returns a scope that includes the friendly finders.

See Also:



200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/friendly_id/base.rb', line 200

def friendly
  # Guess what? This causes Rails to invoke `extend` on the scope, which has
  # the well-known effect of blowing away Ruby's method cache. It would be
  # possible to make this more performant by subclassing the model's
  # relation class, extending that, and returning an instance of it in this
  # method. FriendlyId 4.0 did something similar. However in 5.0 I've
  # decided to only use Rails's public API in order to improve compatibility
  # and maintainability. If you'd like to improve the performance, your
  # efforts would be best directed at improving it at the root cause
  # of the problem - in Rails - because it would benefit more people.
  all.extending(friendly_id_config.finder_methods)
end

- (Object) friendly_id(base = nil, options = {}) {|config| ... }

Configure FriendlyId's behavior in a model.

class Post < ActiveRecord::Base
  extend FriendlyId
  friendly_id :title, :use => :slugged
end

When given the optional block, this method will yield the class's instance of Configuration to the block before evaluating other arguments, so configuration values set in the block may be overwritten by the arguments. This order was chosen to allow passing the same proc to multiple models, while being able to override the values it sets. Here is a contrived example:

$friendly_id_config_proc = Proc.new do |config|
  config.base = :name
  config.use :slugged
end

class Foo < ActiveRecord::Base
  extend FriendlyId
  friendly_id &$friendly_id_config_proc
end

class Bar < ActiveRecord::Base
  extend FriendlyId
  friendly_id :title, &$friendly_id_config_proc
end

However, it's usually better to use FriendlyId.defaults for this:

FriendlyId.defaults do |config|
  config.base = :name
  config.use :slugged
end

class Foo < ActiveRecord::Base
  extend FriendlyId
end

class Bar < ActiveRecord::Base
  extend FriendlyId
  friendly_id :title
end

In general you should use the block syntax either because of your personal aesthetic preference, or because you need to share some functionality between multiple models that can't be well encapsulated by FriendlyId.defaults.

Order Method Calls in a Block vs Ordering Options

When calling this method without a block, you may set the hash options in any order.

However, when using block-style invocation, be sure to call FriendlyId::Configuration's use method prior to the associated configuration options, because it will include modules into your class, and these modules in turn may add required configuration options to the @friendly_id_configuraton's class:

class Person < ActiveRecord::Base
  friendly_id do |config|
    # This will work
    config.use :slugged
    config.sequence_separator = ":"
  end
end

class Person < ActiveRecord::Base
  friendly_id do |config|
    # This will fail
    config.sequence_separator = ":"
    config.use :slugged
  end
end

Including Your Own Modules

Because :use can accept a name or a Module, defaults can be a convenient place to set up behavior common to all classes using FriendlyId. You can include any module, or more conveniently, define one on-the-fly. For example, let's say you want to make Babosa the default slugging library in place of Active Support, and transliterate all slugs from Russian Cyrillic to ASCII:

require "babosa"

FriendlyId.defaults do |config|
  config.base = :name
  config.use :slugged
  config.use Module.new {
    def normalize_friendly_id(text)
      text.to_slug.normalize! :transliterations => [:russian, :latin]
    end
  }
end

Parameters:

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :use (Symbol, Module)

    The addon or name of an addon to use. By default, FriendlyId provides :slugged, :history, :reserved, and :scoped, and :simple_i18n.

  • :reserved_words (Array)

    Available when using :reserved, which is loaded by default. Sets an array of words banned for use as the basis of a friendly_id. By default this includes "edit" and "new".

  • :scope (Symbol)

    Available when using :scoped. Sets the relation or column used to scope generated friendly ids. This option has no default value.

  • :sequence_separator (Symbol)

    Available when using :slugged. Configures the sequence of characters used to separate a slug from a sequence. Defaults to -.

  • :slug_column (Symbol)

    Available when using :slugged. Configures the name of the column where FriendlyId will store the slug. Defaults to :slug.

  • :slug_generator_class (Symbol)

    Available when using :slugged. Sets the class used to generate unique slugs. You should not specify this unless you're doing some extensive hacking on FriendlyId. Defaults to SlugGenerator.

Yields:

  • Provides access to the model class's friendly_id_config, which allows an alternate configuration syntax, and conditional configuration logic.

Yield Parameters:



191
192
193
194
195
196
# File 'lib/friendly_id/base.rb', line 191

def friendly_id(base = nil, options = {}, &block)
  yield friendly_id_config if block_given?
  friendly_id_config.use options.delete :use
  friendly_id_config.send :set, base ? options.merge(:base => base) : options
  include Model
end

- (Object) friendly_id_config

Note:

In the case of Single Table Inheritance (STI), this method will duplicate the parent class's FriendlyId::Configuration and relation class on first access. If you're concerned about thread safety, then be sure to invoke #friendly_id in your class for each model.

Returns the model class's friendly_id_config.



218
219
220
221
222
# File 'lib/friendly_id/base.rb', line 218

def friendly_id_config
  @friendly_id_config ||= base_class.friendly_id_config.dup.tap do |config|
    config.model_class = self
  end
end

- (Object) primary_key_type



224
225
226
# File 'lib/friendly_id/base.rb', line 224

def primary_key_type
  @primary_key_type ||= columns.find { |c| c.name == primary_key}.type
end