/
friendly_id.rb
108 lines (89 loc) · 3.48 KB
/
friendly_id.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# encoding: utf-8
require "thread"
require "friendly_id/base"
require "friendly_id/model"
require "friendly_id/object_utils"
require "friendly_id/configuration"
require "friendly_id/finder_methods"
=begin
== About FriendlyId
FriendlyId is an add-on to Ruby's Active Record that allows you to replace ids
in your URLs with strings:
# without FriendlyId
http://example.com/states/4323454
# with FriendlyId
http://example.com/states/washington
It requires few changes to your application code and offers flexibility,
performance and a well-documented codebase.
=== Core Concepts
==== Slugs
The concept of "slugs[http://en.wikipedia.org/wiki/Slug_(web_publishing)]" is at
the heart of FriendlyId.
A slug is the part of a URL which identifies a page using human-readable
keywords, rather than an opaque identifier such as a numeric id. This can make
your application more friendly both for users and search engine.
==== Finders: Slugs Act Like Numeric IDs
To the extent possible, FriendlyId lets you treat text-based identifiers like
normal IDs. This means that you can perform finds with slugs just like you do
with numeric ids:
Person.find(82542335)
Person.find("joe")
=end
module FriendlyId
# The current version.
VERSION = "4.0.0.beta14"
@mutex = Mutex.new
autoload :History, "friendly_id/history"
autoload :I18n, "friendly_id/i18n"
autoload :Reserved, "friendly_id/reserved"
autoload :Scoped, "friendly_id/scoped"
autoload :Slugged, "friendly_id/slugged"
# FriendlyId takes advantage of `extended` to do basic model setup, primarily
# extending {FriendlyId::Base} to add {FriendlyId::Base#friendly_id
# friendly_id} as a class method.
#
# Previous versions of FriendlyId simply patched ActiveRecord::Base, but this
# version tries to be less invasive.
#
# In addition to adding {FriendlyId::Base#friendly_id friendly_id}, the class
# instance variable +@friendly_id_config+ is added. This variable is an
# instance of an anonymous subclass of {FriendlyId::Configuration}. This
# allows subsequently loaded modules like {FriendlyId::Slugged} and
# {FriendlyId::Scoped} to add functionality to the configuration class only
# for the current class, rather than monkey patching
# {FriendlyId::Configuration} directly. This isolates other models from large
# feature changes an addon to FriendlyId could potentially introduce.
#
# The upshot of this is, you can have two Active Record models that both have
# a @friendly_id_config, but each config object can have different methods
# and behaviors depending on what modules have been loaded, without
# conflicts. Keep this in mind if you're hacking on FriendlyId.
#
# For examples of this, see the source for {Scoped.included}.
def self.extended(model_class)
return if model_class.respond_to? :friendly_id
class << model_class
alias relation_without_friendly_id relation
end
model_class.instance_eval do
extend Base
@friendly_id_config = Class.new(Configuration).new(self)
FriendlyId.defaults.call @friendly_id_config
end
end
# Set global defaults for all models using FriendlyId.
#
# The default defaults are to use the +:reserved+ module and nothing else.
#
# @example
# FriendlyId.defaults do |config|
# config.base = :name
# config.use :slugged
# end
def self.defaults(&block)
@mutex.synchronize do
@defaults = block if block_given?
@defaults ||= lambda {|config| config.use :reserved}
end
end
end