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)
-
- (Object) friendly
Returns a scope that includes the friendly finders.
-
- (Object) friendly_id(base = nil, options = {}) {|config| ... }
Configure FriendlyId's behavior in a model.
-
- (Object) friendly_id_config
Returns the model class's friendly_id_config.
- - (Object) primary_key_type
Instance Method Details
- (Object) friendly
Returns a scope that includes the friendly finders.
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
191 192 193 194 195 196 |
# File 'lib/friendly_id/base.rb', line 191 def friendly_id(base = nil, = {}, &block) yield friendly_id_config if block_given? friendly_id_config.use .delete :use friendly_id_config.send :set, base ? .merge(:base => base) : include Model end |
- (Object) friendly_id_config
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 |