friendly_id 5.0.0.alpha.1 → 5.0.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +2 -1
- data/CONTRIBUTING.md +36 -0
- data/Changelog.md +14 -7
- data/{Guide.rdoc → Guide.md} +172 -155
- data/README.md +9 -8
- data/Rakefile +2 -3
- data/bench.rb +5 -3
- data/friendly_id.gemspec +9 -8
- data/lib/friendly_id.rb +7 -8
- data/lib/friendly_id/base.rb +31 -17
- data/lib/friendly_id/candidates.rb +4 -0
- data/lib/friendly_id/configuration.rb +4 -4
- data/lib/friendly_id/finders.rb +51 -0
- data/lib/friendly_id/history.rb +28 -18
- data/lib/friendly_id/object_utils.rb +7 -7
- data/lib/friendly_id/reserved.rb +3 -3
- data/lib/friendly_id/scoped.rb +19 -19
- data/lib/friendly_id/simple_i18n.rb +28 -28
- data/lib/friendly_id/slugged.rb +122 -101
- data/lib/friendly_id/version.rb +2 -2
- data/test/shared.rb +8 -0
- data/test/slugged_test.rb +1 -1
- metadata +19 -5
- data/WhatsNew.md +0 -3
- data/lib/friendly_id/scopes.rb +0 -28
@@ -19,13 +19,13 @@ module FriendlyId
|
|
19
19
|
# and its value when cast to an integer and then back to a string is
|
20
20
|
# different from its value when merely cast to a string:
|
21
21
|
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
22
|
+
# 123.friendly_id? #=> false
|
23
|
+
# :id.friendly_id? #=> false
|
24
|
+
# {:name => 'joe'}.friendly_id? #=> false
|
25
|
+
# ['name = ?', 'joe'].friendly_id? #=> false
|
26
|
+
# nil.friendly_id? #=> false
|
27
|
+
# "123".friendly_id? #=> nil
|
28
|
+
# "abc123".friendly_id? #=> true
|
29
29
|
def friendly_id?
|
30
30
|
# Considered unfriendly if this is an instance of an unfriendly class or
|
31
31
|
# one of its descendants.
|
data/lib/friendly_id/reserved.rb
CHANGED
@@ -2,7 +2,7 @@ module FriendlyId
|
|
2
2
|
|
3
3
|
=begin
|
4
4
|
|
5
|
-
|
5
|
+
## Reserved Words
|
6
6
|
|
7
7
|
The {FriendlyId::Reserved Reserved} module adds the ability to exlude a list of
|
8
8
|
words from use as FriendlyId slugs.
|
@@ -17,7 +17,7 @@ FriendlyId.defaults}:
|
|
17
17
|
config.reserved_words = %w(new edit nueva nuevo editar)
|
18
18
|
end
|
19
19
|
|
20
|
-
Note that the error message will appear on the field
|
20
|
+
Note that the error message will appear on the field `:friendly_id`. If you are
|
21
21
|
using Rails's scaffolded form errors display, then it will have no field to
|
22
22
|
highlight. If you'd like to change this so that scaffolding works as expected,
|
23
23
|
one way to accomplish this is to move the error message to a different field.
|
@@ -46,7 +46,7 @@ For example:
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
# This module adds the
|
49
|
+
# This module adds the `:reserved_words` configuration option to
|
50
50
|
# {FriendlyId::Configuration FriendlyId::Configuration}.
|
51
51
|
module Configuration
|
52
52
|
attr_writer :reserved_words
|
data/lib/friendly_id/scoped.rb
CHANGED
@@ -4,13 +4,13 @@ module FriendlyId
|
|
4
4
|
|
5
5
|
=begin
|
6
6
|
|
7
|
-
|
7
|
+
## Unique Slugs by Scope
|
8
8
|
|
9
9
|
The {FriendlyId::Scoped} module allows FriendlyId to generate unique slugs
|
10
10
|
within a scope.
|
11
11
|
|
12
12
|
This allows, for example, two restaurants in different cities to have the slug
|
13
|
-
|
13
|
+
`joes-diner`:
|
14
14
|
|
15
15
|
class Restaurant < ActiveRecord::Base
|
16
16
|
extend FriendlyId
|
@@ -24,16 +24,16 @@ This allows, for example, two restaurants in different cities to have the slug
|
|
24
24
|
friendly_id :name, :use => :slugged
|
25
25
|
end
|
26
26
|
|
27
|
-
City.find("seattle").restaurants.find("joes-diner")
|
28
|
-
City.find("chicago").restaurants.find("joes-diner")
|
27
|
+
City.friendly.find("seattle").restaurants.friendly.find("joes-diner")
|
28
|
+
City.friendly.find("chicago").restaurants.friendly.find("joes-diner")
|
29
29
|
|
30
30
|
Without :scoped in this case, one of the restaurants would have the slug
|
31
|
-
|
31
|
+
`joes-diner` and the other would have `joes-diner-f9f3789a-daec-4156-af1d-fab81aa16ee5`.
|
32
32
|
|
33
|
-
The value for the
|
33
|
+
The value for the `:scope` option can be the name of a `belongs_to` relation, or
|
34
34
|
a column.
|
35
35
|
|
36
|
-
Additionally, the
|
36
|
+
Additionally, the `:scope` option can receive an array of scope values:
|
37
37
|
|
38
38
|
class Cuisine < ActiveRecord::Base
|
39
39
|
extend FriendlyId
|
@@ -55,30 +55,30 @@ Additionally, the +:scope+ option can receive an array of scope values:
|
|
55
55
|
|
56
56
|
All supplied values will be used to determine scope.
|
57
57
|
|
58
|
-
|
58
|
+
### Finding Records by Friendly ID
|
59
59
|
|
60
60
|
If you are using scopes your friendly ids may not be unique, so a simple find
|
61
61
|
like
|
62
62
|
|
63
|
-
Restaurant.find("joes-diner")
|
63
|
+
Restaurant.friendly.find("joes-diner")
|
64
64
|
|
65
65
|
may return the wrong record. In these cases it's best to query through the
|
66
66
|
relation:
|
67
67
|
|
68
|
-
@city.restaurants.find("joes-diner")
|
68
|
+
@city.restaurants.friendly.find("joes-diner")
|
69
69
|
|
70
70
|
Alternatively, you could pass the scope value as a query parameter:
|
71
71
|
|
72
|
-
Restaurant.find("joes-diner").where(:city_id => @city.id)
|
72
|
+
Restaurant.friendly.find("joes-diner").where(:city_id => @city.id)
|
73
73
|
|
74
74
|
|
75
|
-
|
75
|
+
### Finding All Records That Match a Scoped ID
|
76
76
|
|
77
77
|
Query the slug column directly:
|
78
78
|
|
79
|
-
Restaurant.
|
79
|
+
Restaurant.where(:slug => "joes-diner")
|
80
80
|
|
81
|
-
|
81
|
+
### Routes for Scoped Models
|
82
82
|
|
83
83
|
Recall that FriendlyId is a database-centric library, and does not set up any
|
84
84
|
routes for scoped models. You must do this yourself in your application. Here's
|
@@ -93,8 +93,8 @@ an example of one way to set this up:
|
|
93
93
|
<%= link_to 'Show', [@city, @restaurant] %>
|
94
94
|
|
95
95
|
# in controllers
|
96
|
-
@city = City.find(params[:city_id])
|
97
|
-
@restaurant = @city.restaurants.find(params[:id])
|
96
|
+
@city = City.friendly.find(params[:city_id])
|
97
|
+
@restaurant = @city.restaurants.friendly.find(params[:id])
|
98
98
|
|
99
99
|
# URLs:
|
100
100
|
http://example.org/cities/seattle/restaurants/joes-diner
|
@@ -130,21 +130,21 @@ an example of one way to set this up:
|
|
130
130
|
end
|
131
131
|
private :slug_generator
|
132
132
|
|
133
|
-
# This module adds the
|
133
|
+
# This module adds the `:scope` configuration option to
|
134
134
|
# {FriendlyId::Configuration FriendlyId::Configuration}.
|
135
135
|
module Configuration
|
136
136
|
|
137
137
|
# Gets the scope value.
|
138
138
|
#
|
139
139
|
# When setting this value, the argument should be a symbol referencing a
|
140
|
-
#
|
140
|
+
# `belongs_to` relation, or a column.
|
141
141
|
#
|
142
142
|
# @return Symbol The scope value
|
143
143
|
attr_accessor :scope
|
144
144
|
|
145
145
|
# Gets the scope columns.
|
146
146
|
#
|
147
|
-
# Checks to see if the
|
147
|
+
# Checks to see if the `:scope` option passed to
|
148
148
|
# {FriendlyId::Base#friendly_id} refers to a relation, and if so, returns
|
149
149
|
# the realtion's foreign key. Otherwise it assumes the option value was
|
150
150
|
# the name of column and returns it cast to a String.
|
@@ -4,7 +4,7 @@ module FriendlyId
|
|
4
4
|
|
5
5
|
=begin
|
6
6
|
|
7
|
-
|
7
|
+
## Translating Slugs Using Simple I18n
|
8
8
|
|
9
9
|
The {FriendlyId::SimpleI18n SimpleI18n} module adds very basic i18n support to
|
10
10
|
FriendlyId.
|
@@ -12,61 +12,61 @@ FriendlyId.
|
|
12
12
|
In order to use this module, your model must have a slug column for each locale.
|
13
13
|
By default FriendlyId looks for columns named, for example, "slug_en",
|
14
14
|
"slug_es", etc. The first part of the name can be configured by passing the
|
15
|
-
|
15
|
+
`:slug_column` option if you choose. Note that the column for the default locale
|
16
16
|
must also include the locale in its name.
|
17
17
|
|
18
18
|
This module is most suitable to applications that need to support few locales.
|
19
19
|
If you need to support two or more locales, you may wish to use the
|
20
20
|
friendly_id_globalize gem instead.
|
21
21
|
|
22
|
-
|
22
|
+
### Example migration
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
24
|
+
def self.up
|
25
|
+
create_table :posts do |t|
|
26
|
+
t.string :title
|
27
|
+
t.string :slug_en
|
28
|
+
t.string :slug_es
|
29
|
+
t.text :body
|
30
|
+
end
|
31
|
+
add_index :posts, :slug_en
|
32
|
+
add_index :posts, :slug_es
|
30
33
|
end
|
31
|
-
add_index :posts, :slug_en
|
32
|
-
add_index :posts, :slug_es
|
33
|
-
end
|
34
34
|
|
35
|
-
|
35
|
+
### Finds
|
36
36
|
|
37
37
|
Finds will take into consideration the current locale:
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
39
|
+
I18n.locale = :es
|
40
|
+
Post.find("la-guerra-de-las-galaxas")
|
41
|
+
I18n.locale = :en
|
42
|
+
Post.find("star-wars")
|
43
43
|
|
44
44
|
To find a slug by an explicit locale, perform the find inside a block
|
45
|
-
passed to I18n's
|
45
|
+
passed to I18n's `with_locale` method:
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
I18n.with_locale(:es) do
|
48
|
+
Post.find("la-guerra-de-las-galaxas")
|
49
|
+
end
|
50
50
|
|
51
|
-
|
51
|
+
### Creating Records
|
52
52
|
|
53
53
|
When new records are created, the slug is generated for the current locale only.
|
54
54
|
|
55
|
-
|
55
|
+
### Translating Slugs
|
56
56
|
|
57
57
|
To translate an existing record's friendly_id, use
|
58
58
|
{FriendlyId::SimpleI18n::Model#set_friendly_id}. This will ensure that the slug
|
59
59
|
you add is properly escaped, transliterated and sequenced:
|
60
60
|
|
61
|
-
|
62
|
-
|
61
|
+
post = Post.create :name => "Star Wars"
|
62
|
+
post.set_friendly_id("La guerra de las galaxas", :es)
|
63
63
|
|
64
64
|
If you don't pass in a locale argument, FriendlyId::SimpleI18n will just use the
|
65
65
|
current locale:
|
66
66
|
|
67
|
-
|
68
|
-
|
69
|
-
|
67
|
+
I18n.with_locale(:es) do
|
68
|
+
post.set_friendly_id("La guerra de las galaxas")
|
69
|
+
end
|
70
70
|
=end
|
71
71
|
module SimpleI18n
|
72
72
|
|
data/lib/friendly_id/slugged.rb
CHANGED
@@ -5,7 +5,7 @@ require "friendly_id/candidates"
|
|
5
5
|
module FriendlyId
|
6
6
|
=begin
|
7
7
|
|
8
|
-
|
8
|
+
## Slugged Models
|
9
9
|
|
10
10
|
FriendlyId can use a separate column to store slugs for models which require
|
11
11
|
some text processing.
|
@@ -30,13 +30,13 @@ To activate the slugging functionality, use the {FriendlyId::Slugged} module.
|
|
30
30
|
|
31
31
|
FriendlyId will generate slugs from a method or column that you specify, and
|
32
32
|
store them in a field in your model. By default, this field must be named
|
33
|
-
|
33
|
+
`:slug`, though you may change this using the
|
34
34
|
{FriendlyId::Slugged::Configuration#slug_column slug_column} configuration
|
35
35
|
option. You should add an index to this column, and in most cases, make it
|
36
36
|
unique. You may also wish to constrain it to NOT NULL, but this depends on your
|
37
37
|
app's behavior and requirements.
|
38
38
|
|
39
|
-
|
39
|
+
### Example Setup
|
40
40
|
|
41
41
|
# your model
|
42
42
|
class Post < ActiveRecord::Base
|
@@ -62,119 +62,144 @@ app's behavior and requirements.
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
-
|
65
|
+
### Working With Slugs
|
66
66
|
|
67
|
-
|
67
|
+
#### Formatting
|
68
68
|
|
69
69
|
By default, FriendlyId uses Active Support's
|
70
|
-
paramaterize
|
70
|
+
[paramaterize](http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-parameterize)
|
71
71
|
method to create slugs. This method will intelligently replace spaces with
|
72
72
|
dashes, and Unicode Latin characters with ASCII approximations:
|
73
73
|
|
74
|
-
|
75
|
-
|
74
|
+
movie = Movie.create! :title => "Der Preis fürs Überleben"
|
75
|
+
movie.slug #=> "der-preis-furs-uberleben"
|
76
76
|
|
77
|
-
|
77
|
+
#### Column or Method?
|
78
78
|
|
79
|
-
|
80
|
-
|
79
|
+
FriendlyId always uses a method as the basis of the slug text - not a column. It
|
80
|
+
first glance, this may sound confusing, but remember that Active Record provides
|
81
|
+
methods for each column in a model's associated table, and that's what
|
82
|
+
FriendlyId uses.
|
81
83
|
|
82
|
-
|
83
|
-
car2 = Car.create :title => "Peugot 206"
|
84
|
+
Here's an example of a class that uses a custom method to generate the slug:
|
84
85
|
|
85
|
-
|
86
|
-
|
86
|
+
class Person < ActiveRecord::Base
|
87
|
+
friendly_id :name_and_location
|
88
|
+
def name_and_location
|
89
|
+
"#{name} from #{location}"
|
90
|
+
end
|
91
|
+
end
|
87
92
|
|
88
|
-
|
93
|
+
bob = Person.create! :name => "Bob Smith", :location => "New York City"
|
94
|
+
bob.friendly_id #=> "bob-smith-from-new-york-city"
|
89
95
|
|
90
|
-
|
96
|
+
FriendlyId refers to this internally as the "base" method.
|
91
97
|
|
92
|
-
|
93
|
-
sequence_separator} configuration option.
|
98
|
+
#### Uniqueness
|
94
99
|
|
95
|
-
|
100
|
+
When you try to insert a record that would generate a duplicate friendly id,
|
101
|
+
FriendlyId will append a UUID to the generated slug to ensure uniqueness:
|
96
102
|
|
97
|
-
|
98
|
-
|
99
|
-
methods for each column in a model's associated table, and that's what
|
100
|
-
FriendlyId uses.
|
103
|
+
car = Car.create :title => "Peugot 206"
|
104
|
+
car2 = Car.create :title => "Peugot 206"
|
101
105
|
|
102
|
-
|
106
|
+
car.friendly_id #=> "peugot-206"
|
107
|
+
car2.friendly_id #=> "peugot-206-f9f3789a-daec-4156-af1d-fab81aa16ee5"
|
108
|
+
|
109
|
+
Previous versions of FriendlyId appended a numeric sequence a to make slugs
|
110
|
+
unique, but this was removed to simplify using FriendlyId in concurrent code.
|
111
|
+
|
112
|
+
#### Candidates
|
113
|
+
|
114
|
+
Since UUIDs are ugly, FriendlyId provides a "slug candidates" functionality to
|
115
|
+
let you specify alternate slugs to use in the event the one you want to use is
|
116
|
+
already taken. For example:
|
103
117
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
118
|
+
class Restaurant < ActiveRecord::Base
|
119
|
+
extend FriendlyId
|
120
|
+
friendly_id :slug_candidates, use: :slugged
|
121
|
+
|
122
|
+
# Try building a slug based on the following fields in
|
123
|
+
# increasing order of specificity.
|
124
|
+
def slug_candidates
|
125
|
+
[
|
126
|
+
:name,
|
127
|
+
[:name, :city],
|
128
|
+
[:name, :street, :city],
|
129
|
+
[:name, :street_number, :street, :city]
|
130
|
+
]
|
131
|
+
end
|
108
132
|
end
|
109
|
-
end
|
110
133
|
|
111
|
-
|
112
|
-
|
134
|
+
r1 = Restaurant.create! name: 'Plaza Diner', city: 'New Paltz'
|
135
|
+
r2 = Restaurant.create! name: 'Plaza Diner', city: 'Kingston'
|
113
136
|
|
114
|
-
|
137
|
+
r1.friendly_id #=> 'plaza-diner'
|
138
|
+
r2.friendly_id #=> 'plaza-diner-kingston'
|
115
139
|
|
116
|
-
|
117
|
-
|
140
|
+
To use candidates, make your FriendlyId base method return an array. The
|
141
|
+
method need not be named `slug_candidates`; it can be anything you want. The
|
142
|
+
array may contain any combination of symbols, strings, procs or lambdas and
|
143
|
+
will be evaluated lazily and in order. If you include symbols, FriendlyId will
|
144
|
+
invoke a method on your model class with the same name. Strings will be
|
145
|
+
interpreted literally. Procs and lambdas will be called and their return values
|
146
|
+
used as the basis of the friendly id. If none of the candidates can generate a
|
147
|
+
unique slug, then FriendlyId will append a UUID to the first candidate as a
|
148
|
+
last resort.
|
118
149
|
|
119
|
-
|
150
|
+
#### Sequence Separator
|
120
151
|
|
121
|
-
|
122
|
-
control whether new friendly ids are created when a model is updated. For
|
123
|
-
example, if you only want to generate slugs once and then treat them as
|
124
|
-
read-only:
|
152
|
+
By default, FriendlyId uses a dash to separate the slug from a sequence.
|
125
153
|
|
126
|
-
|
127
|
-
|
128
|
-
friendly_id :title, :use => :slugged
|
154
|
+
You can change this with the {FriendlyId::Slugged::Configuration#sequence_separator
|
155
|
+
sequence_separator} configuration option.
|
129
156
|
|
130
|
-
|
131
|
-
new_record?
|
132
|
-
end
|
133
|
-
end
|
157
|
+
#### Providing Your Own Slug Processing Method
|
134
158
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
post.save!
|
139
|
-
post.slug #=> "hello-world"
|
159
|
+
You can override {FriendlyId::Slugged#normalize_friendly_id} in your model for
|
160
|
+
total control over the slug format. It will be invoked for any generated slug,
|
161
|
+
whether for a single slug or for slug candidates.
|
140
162
|
|
141
|
-
|
163
|
+
#### Deciding When to Generate New Slugs
|
142
164
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
locale when replacing Latin characters:
|
165
|
+
Previous versions of FriendlyId provided a method named
|
166
|
+
`should_generate_new_friendly_id?` which you could override to control when new
|
167
|
+
slugs were generated.
|
147
168
|
|
148
|
-
|
149
|
-
|
150
|
-
i18n:
|
151
|
-
transliterate:
|
152
|
-
rule:
|
153
|
-
ü: "ue"
|
154
|
-
ö: "oe"
|
155
|
-
etc...
|
169
|
+
As of FriendlyId 5.0, slugs are only generated when the `slug` field is nil. If
|
170
|
+
you want a slug to be regenerated, you must explicity set the field to nil:
|
156
171
|
|
157
|
-
|
158
|
-
|
172
|
+
restaurant.friendly_id # joes-diner
|
173
|
+
restaurant.name = "The Plaza Diner"
|
174
|
+
restaurant.save!
|
175
|
+
restaurant.friendly_id # joes-diner
|
176
|
+
restaurant.slug = nil
|
177
|
+
restaurant.save!
|
178
|
+
restaurant.friendly_id # the-plaza-diner
|
159
179
|
|
160
|
-
This functionality was in fact taken from earlier versions of FriendlyId.
|
161
180
|
|
162
|
-
|
181
|
+
#### Locale-specific Transliterations
|
163
182
|
|
164
|
-
|
183
|
+
Active Support's `parameterize` uses
|
184
|
+
[transliterate](http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-transliterate),
|
185
|
+
which in turn can use I18n's transliteration rules to consider the current
|
186
|
+
locale when replacing Latin characters:
|
165
187
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
188
|
+
# config/locales/de.yml
|
189
|
+
de:
|
190
|
+
i18n:
|
191
|
+
transliterate:
|
192
|
+
rule:
|
193
|
+
ü: "ue"
|
194
|
+
ö: "oe"
|
195
|
+
etc...
|
170
196
|
|
171
|
-
|
197
|
+
movie = Movie.create! :title => "Der Preis fürs Überleben"
|
198
|
+
movie.slug #=> "der-preis-fuers-ueberleben"
|
172
199
|
|
173
|
-
|
174
|
-
* Use explicit finders like +find_by_id+ to always find by the numeric id, or
|
175
|
-
+find_by_slug+ to always find using the friendly id.
|
200
|
+
This functionality was in fact taken from earlier versions of FriendlyId.
|
176
201
|
|
177
|
-
|
202
|
+
#### Gotchas: Common Problems
|
178
203
|
|
179
204
|
FriendlyId uses a before_validation callback to generate and set the slug. This
|
180
205
|
means that if you create two model instances before saving them, it's possible
|
@@ -185,12 +210,8 @@ attributes creates more than one record for a model that uses friendly_id. The
|
|
185
210
|
second, in concurrent code, either in threads or multiple processes.
|
186
211
|
|
187
212
|
To solve the nested attributes issue, I recommend simply avoiding them when
|
188
|
-
creating more than one nested record for a model that uses FriendlyId. See
|
189
|
-
Github issue
|
190
|
-
|
191
|
-
To solve the concurrency issue, I recommend locking the model's table against
|
192
|
-
inserts while when saving the record. See {this Github
|
193
|
-
issue}[https://github.com/FriendlyId/friendly_id/issues/180] for discussion.
|
213
|
+
creating more than one nested record for a model that uses FriendlyId. See [this
|
214
|
+
Github issue](https://github.com/norman/friendly_id/issues/185) for discussion.
|
194
215
|
|
195
216
|
=end
|
196
217
|
module Slugged
|
@@ -216,25 +237,25 @@ issue}[https://github.com/FriendlyId/friendly_id/issues/180] for discussion.
|
|
216
237
|
# you can override this method in your model class to control exactly how
|
217
238
|
# slugs are generated.
|
218
239
|
#
|
219
|
-
#
|
240
|
+
# ### Example
|
220
241
|
#
|
221
|
-
#
|
222
|
-
#
|
242
|
+
# class Person < ActiveRecord::Base
|
243
|
+
# friendly_id :name_and_location
|
223
244
|
#
|
224
|
-
#
|
225
|
-
#
|
226
|
-
#
|
245
|
+
# def name_and_location
|
246
|
+
# "#{name} from #{location}"
|
247
|
+
# end
|
227
248
|
#
|
228
|
-
#
|
229
|
-
#
|
230
|
-
#
|
249
|
+
# # Use default slug, but upper case and with underscores
|
250
|
+
# def normalize_friendly_id(string)
|
251
|
+
# super.upcase.gsub("-", "_")
|
252
|
+
# end
|
231
253
|
# end
|
232
|
-
# end
|
233
254
|
#
|
234
|
-
#
|
235
|
-
#
|
255
|
+
# bob = Person.create! :name => "Bob Smith", :location => "New York City"
|
256
|
+
# bob.friendly_id #=> "BOB_SMITH_FROM_NEW_YORK_CITY"
|
236
257
|
#
|
237
|
-
#
|
258
|
+
# ### More Resources
|
238
259
|
#
|
239
260
|
# You might want to look into Babosa[https://github.com/norman/babosa],
|
240
261
|
# which is the slugging library used by FriendlyId prior to version 4, which
|
@@ -273,8 +294,8 @@ issue}[https://github.com/FriendlyId/friendly_id/issues/180] for discussion.
|
|
273
294
|
end
|
274
295
|
private :slug_generator
|
275
296
|
|
276
|
-
# This module adds the
|
277
|
-
#
|
297
|
+
# This module adds the `:slug_column`, and `:sequence_separator`, and
|
298
|
+
# `:slug_generator_class` configuration options to
|
278
299
|
# {FriendlyId::Configuration FriendlyId::Configuration}.
|
279
300
|
module Configuration
|
280
301
|
attr_writer :slug_column, :sequence_separator
|
@@ -291,7 +312,7 @@ issue}[https://github.com/FriendlyId/friendly_id/issues/180] for discussion.
|
|
291
312
|
# You can change the default separator by setting the
|
292
313
|
# {FriendlyId::Slugged::Configuration#sequence_separator
|
293
314
|
# sequence_separator} configuration option.
|
294
|
-
# @return String The sequence separator string. Defaults to "
|
315
|
+
# @return String The sequence separator string. Defaults to "`-`".
|
295
316
|
def sequence_separator
|
296
317
|
@sequence_separator or defaults[:sequence_separator]
|
297
318
|
end
|