friendly_id 5.4.2 → 5.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/dependabot.yml +6 -0
  4. data/.github/workflows/test.yml +38 -25
  5. data/.yardopts +2 -0
  6. data/Changelog.md +10 -0
  7. data/Gemfile +9 -13
  8. data/README.md +21 -0
  9. data/Rakefile +24 -27
  10. data/bench.rb +30 -27
  11. data/certs/parndt.pem +25 -23
  12. data/friendly_id.gemspec +26 -29
  13. data/gemfiles/Gemfile.rails-5.2.rb +11 -16
  14. data/gemfiles/Gemfile.rails-6.0.rb +11 -16
  15. data/gemfiles/Gemfile.rails-6.1.rb +22 -0
  16. data/gemfiles/Gemfile.rails-7.0.rb +22 -0
  17. data/guide.rb +13 -6
  18. data/lib/friendly_id/base.rb +59 -60
  19. data/lib/friendly_id/candidates.rb +9 -11
  20. data/lib/friendly_id/configuration.rb +6 -7
  21. data/lib/friendly_id/finder_methods.rb +26 -11
  22. data/lib/friendly_id/finders.rb +66 -66
  23. data/lib/friendly_id/history.rb +62 -63
  24. data/lib/friendly_id/initializer.rb +4 -4
  25. data/lib/friendly_id/migration.rb +6 -6
  26. data/lib/friendly_id/object_utils.rb +2 -2
  27. data/lib/friendly_id/reserved.rb +30 -32
  28. data/lib/friendly_id/scoped.rb +99 -102
  29. data/lib/friendly_id/sequentially_slugged/calculator.rb +69 -0
  30. data/lib/friendly_id/sequentially_slugged.rb +17 -64
  31. data/lib/friendly_id/simple_i18n.rb +78 -69
  32. data/lib/friendly_id/slug.rb +1 -2
  33. data/lib/friendly_id/slug_generator.rb +1 -3
  34. data/lib/friendly_id/slugged.rb +236 -238
  35. data/lib/friendly_id/version.rb +1 -1
  36. data/lib/friendly_id.rb +47 -49
  37. data/lib/generators/friendly_id_generator.rb +9 -9
  38. data/test/base_test.rb +10 -13
  39. data/test/benchmarks/finders.rb +28 -26
  40. data/test/benchmarks/object_utils.rb +13 -13
  41. data/test/candidates_test.rb +17 -18
  42. data/test/configuration_test.rb +7 -11
  43. data/test/core_test.rb +1 -2
  44. data/test/databases.yml +4 -3
  45. data/test/finders_test.rb +52 -5
  46. data/test/generator_test.rb +16 -26
  47. data/test/helper.rb +31 -24
  48. data/test/history_test.rb +70 -74
  49. data/test/numeric_slug_test.rb +4 -4
  50. data/test/object_utils_test.rb +0 -2
  51. data/test/reserved_test.rb +9 -11
  52. data/test/schema.rb +5 -4
  53. data/test/scoped_test.rb +18 -20
  54. data/test/sequentially_slugged_test.rb +65 -50
  55. data/test/shared.rb +15 -16
  56. data/test/simple_i18n_test.rb +22 -12
  57. data/test/slugged_test.rb +102 -121
  58. data/test/sti_test.rb +19 -21
  59. data.tar.gz.sig +0 -0
  60. metadata +37 -32
  61. metadata.gz.sig +0 -0
@@ -1,251 +1,249 @@
1
- # encoding: utf-8
2
1
  require "friendly_id/slug_generator"
3
2
  require "friendly_id/candidates"
4
3
 
5
4
  module FriendlyId
6
- =begin
7
-
8
- ## Slugged Models
9
-
10
- FriendlyId can use a separate column to store slugs for models which require
11
- some text processing.
12
-
13
- For example, blog applications typically use a post title to provide the basis
14
- of a search engine friendly URL. Such identifiers typically lack uppercase
15
- characters, use ASCII to approximate UTF-8 characters, and strip out other
16
- characters which may make them aesthetically unappealing or error-prone when
17
- used in a URL.
18
-
19
- class Post < ActiveRecord::Base
20
- extend FriendlyId
21
- friendly_id :title, :use => :slugged
22
- end
23
-
24
- @post = Post.create(:title => "This is the first post!")
25
- @post.friendly_id # returns "this-is-the-first-post"
26
- redirect_to @post # the URL will be /posts/this-is-the-first-post
27
-
28
- In general, use slugs by default unless you know for sure you don't need them.
29
- To activate the slugging functionality, use the {FriendlyId::Slugged} module.
30
-
31
- FriendlyId will generate slugs from a method or column that you specify, and
32
- store them in a field in your model. By default, this field must be named
33
- `:slug`, though you may change this using the
34
- {FriendlyId::Slugged::Configuration#slug_column slug_column} configuration
35
- option. You should add an index to this column, and in most cases, make it
36
- unique. You may also wish to constrain it to NOT NULL, but this depends on your
37
- app's behavior and requirements.
38
-
39
- ### Example Setup
40
-
41
- # your model
42
- class Post < ActiveRecord::Base
43
- extend FriendlyId
44
- friendly_id :title, :use => :slugged
45
- validates_presence_of :title, :slug, :body
46
- end
47
-
48
- # a migration
49
- class CreatePosts < ActiveRecord::Migration
50
- def self.up
51
- create_table :posts do |t|
52
- t.string :title, :null => false
53
- t.string :slug, :null => false
54
- t.text :body
55
- end
56
-
57
- add_index :posts, :slug, :unique => true
58
- end
59
-
60
- def self.down
61
- drop_table :posts
62
- end
63
- end
64
-
65
- ### Working With Slugs
66
-
67
- #### Formatting
68
-
69
- By default, FriendlyId uses Active Support's
70
- [parameterize](http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-parameterize)
71
- method to create slugs. This method will intelligently replace spaces with
72
- dashes, and Unicode Latin characters with ASCII approximations:
73
-
74
- movie = Movie.create! :title => "Der Preis fürs Überleben"
75
- movie.slug #=> "der-preis-furs-uberleben"
76
-
77
- #### Column or Method?
78
-
79
- FriendlyId always uses a method as the basis of the slug text - not a column. At
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.
83
-
84
- Here's an example of a class that uses a custom method to generate the slug:
85
-
86
- class Person < ActiveRecord::Base
87
- extend FriendlyId
88
- friendly_id :name_and_location, use: :slugged
89
-
90
- def name_and_location
91
- "#{name} from #{location}"
92
- end
93
- end
94
-
95
- bob = Person.create! :name => "Bob Smith", :location => "New York City"
96
- bob.friendly_id #=> "bob-smith-from-new-york-city"
97
-
98
- FriendlyId refers to this internally as the "base" method.
99
-
100
- #### Uniqueness
101
-
102
- When you try to insert a record that would generate a duplicate friendly id,
103
- FriendlyId will append a UUID to the generated slug to ensure uniqueness:
104
-
105
- car = Car.create :title => "Peugeot 206"
106
- car2 = Car.create :title => "Peugeot 206"
107
-
108
- car.friendly_id #=> "peugeot-206"
109
- car2.friendly_id #=> "peugeot-206-f9f3789a-daec-4156-af1d-fab81aa16ee5"
110
-
111
- Previous versions of FriendlyId appended a numeric sequence to make slugs
112
- unique, but this was removed to simplify using FriendlyId in concurrent code.
113
-
114
- #### Candidates
115
-
116
- Since UUIDs are ugly, FriendlyId provides a "slug candidates" functionality to
117
- let you specify alternate slugs to use in the event the one you want to use is
118
- already taken. For example:
119
-
120
- class Restaurant < ActiveRecord::Base
121
- extend FriendlyId
122
- friendly_id :slug_candidates, use: :slugged
123
-
124
- # Try building a slug based on the following fields in
125
- # increasing order of specificity.
126
- def slug_candidates
127
- [
128
- :name,
129
- [:name, :city],
130
- [:name, :street, :city],
131
- [:name, :street_number, :street, :city]
132
- ]
133
- end
134
- end
135
-
136
- r1 = Restaurant.create! name: 'Plaza Diner', city: 'New Paltz'
137
- r2 = Restaurant.create! name: 'Plaza Diner', city: 'Kingston'
138
-
139
- r1.friendly_id #=> 'plaza-diner'
140
- r2.friendly_id #=> 'plaza-diner-kingston'
141
-
142
- To use candidates, make your FriendlyId base method return an array. The
143
- method need not be named `slug_candidates`; it can be anything you want. The
144
- array may contain any combination of symbols, strings, procs or lambdas and
145
- will be evaluated lazily and in order. If you include symbols, FriendlyId will
146
- invoke a method on your model class with the same name. Strings will be
147
- interpreted literally. Procs and lambdas will be called and their return values
148
- used as the basis of the friendly id. If none of the candidates can generate a
149
- unique slug, then FriendlyId will append a UUID to the first candidate as a
150
- last resort.
151
-
152
- #### Sequence Separator
153
-
154
- By default, FriendlyId uses a dash to separate the slug from a sequence.
155
-
156
- You can change this with the {FriendlyId::Slugged::Configuration#sequence_separator
157
- sequence_separator} configuration option.
158
-
159
- #### Providing Your Own Slug Processing Method
160
-
161
- You can override {FriendlyId::Slugged#normalize_friendly_id} in your model for
162
- total control over the slug format. It will be invoked for any generated slug,
163
- whether for a single slug or for slug candidates.
164
-
165
- #### Deciding When to Generate New Slugs
166
-
167
- As of FriendlyId 5.0, slugs are only generated when the `slug` field is nil. If
168
- you want a slug to be regenerated,set the slug field to nil:
169
-
170
- restaurant.friendly_id # joes-diner
171
- restaurant.name = "The Plaza Diner"
172
- restaurant.save!
173
- restaurant.friendly_id # joes-diner
174
- restaurant.slug = nil
175
- restaurant.save!
176
- restaurant.friendly_id # the-plaza-diner
177
-
178
- You can also override the
179
- {FriendlyId::Slugged#should_generate_new_friendly_id?} method, which lets you
180
- control exactly when new friendly ids are set:
181
-
182
- class Post < ActiveRecord::Base
183
- extend FriendlyId
184
- friendly_id :title, :use => :slugged
185
-
186
- def should_generate_new_friendly_id?
187
- title_changed?
188
- end
189
- end
190
-
191
- If you want to extend the default behavior but add your own conditions,
192
- don't forget to invoke `super` from your implementation:
193
-
194
- class Category < ActiveRecord::Base
195
- extend FriendlyId
196
- friendly_id :name, :use => :slugged
197
-
198
- def should_generate_new_friendly_id?
199
- name_changed? || super
200
- end
201
- end
202
-
203
- #### Locale-specific Transliterations
204
-
205
- Active Support's `parameterize` uses
206
- [transliterate](http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-transliterate),
207
- which in turn can use I18n's transliteration rules to consider the current
208
- locale when replacing Latin characters:
209
-
210
- # config/locales/de.yml
211
- de:
212
- i18n:
213
- transliterate:
214
- rule:
215
- ü: "ue"
216
- ö: "oe"
217
- etc...
218
-
219
- movie = Movie.create! :title => "Der Preis fürs Überleben"
220
- movie.slug #=> "der-preis-fuers-ueberleben"
221
-
222
- This functionality was in fact taken from earlier versions of FriendlyId.
223
-
224
- #### Gotchas: Common Problems
225
-
226
- FriendlyId uses a before_validation callback to generate and set the slug. This
227
- means that if you create two model instances before saving them, it's possible
228
- they will generate the same slug, and the second save will fail.
229
-
230
- This can happen in two fairly normal cases: the first, when a model using nested
231
- attributes creates more than one record for a model that uses friendly_id. The
232
- second, in concurrent code, either in threads or multiple processes.
233
-
234
- To solve the nested attributes issue, I recommend simply avoiding them when
235
- creating more than one nested record for a model that uses FriendlyId. See [this
236
- Github issue](https://github.com/norman/friendly_id/issues/185) for discussion.
237
-
238
- =end
5
+ # @guide begin
6
+ #
7
+ # ## Slugged Models
8
+ #
9
+ # FriendlyId can use a separate column to store slugs for models which require
10
+ # some text processing.
11
+ #
12
+ # For example, blog applications typically use a post title to provide the basis
13
+ # of a search engine friendly URL. Such identifiers typically lack uppercase
14
+ # characters, use ASCII to approximate UTF-8 characters, and strip out other
15
+ # characters which may make them aesthetically unappealing or error-prone when
16
+ # used in a URL.
17
+ #
18
+ # class Post < ActiveRecord::Base
19
+ # extend FriendlyId
20
+ # friendly_id :title, :use => :slugged
21
+ # end
22
+ #
23
+ # @post = Post.create(:title => "This is the first post!")
24
+ # @post.friendly_id # returns "this-is-the-first-post"
25
+ # redirect_to @post # the URL will be /posts/this-is-the-first-post
26
+ #
27
+ # In general, use slugs by default unless you know for sure you don't need them.
28
+ # To activate the slugging functionality, use the {FriendlyId::Slugged} module.
29
+ #
30
+ # FriendlyId will generate slugs from a method or column that you specify, and
31
+ # store them in a field in your model. By default, this field must be named
32
+ # `:slug`, though you may change this using the
33
+ # {FriendlyId::Slugged::Configuration#slug_column slug_column} configuration
34
+ # option. You should add an index to this column, and in most cases, make it
35
+ # unique. You may also wish to constrain it to NOT NULL, but this depends on your
36
+ # app's behavior and requirements.
37
+ #
38
+ # ### Example Setup
39
+ #
40
+ # # your model
41
+ # class Post < ActiveRecord::Base
42
+ # extend FriendlyId
43
+ # friendly_id :title, :use => :slugged
44
+ # validates_presence_of :title, :slug, :body
45
+ # end
46
+ #
47
+ # # a migration
48
+ # class CreatePosts < ActiveRecord::Migration
49
+ # def self.up
50
+ # create_table :posts do |t|
51
+ # t.string :title, :null => false
52
+ # t.string :slug, :null => false
53
+ # t.text :body
54
+ # end
55
+ #
56
+ # add_index :posts, :slug, :unique => true
57
+ # end
58
+ #
59
+ # def self.down
60
+ # drop_table :posts
61
+ # end
62
+ # end
63
+ #
64
+ # ### Working With Slugs
65
+ #
66
+ # #### Formatting
67
+ #
68
+ # By default, FriendlyId uses Active Support's
69
+ # [parameterize](http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-parameterize)
70
+ # method to create slugs. This method will intelligently replace spaces with
71
+ # dashes, and Unicode Latin characters with ASCII approximations:
72
+ #
73
+ # movie = Movie.create! :title => "Der Preis fürs Überleben"
74
+ # movie.slug #=> "der-preis-furs-uberleben"
75
+ #
76
+ # #### Column or Method?
77
+ #
78
+ # FriendlyId always uses a method as the basis of the slug text - not a column. At
79
+ # first glance, this may sound confusing, but remember that Active Record provides
80
+ # methods for each column in a model's associated table, and that's what
81
+ # FriendlyId uses.
82
+ #
83
+ # Here's an example of a class that uses a custom method to generate the slug:
84
+ #
85
+ # class Person < ActiveRecord::Base
86
+ # extend FriendlyId
87
+ # friendly_id :name_and_location, use: :slugged
88
+ #
89
+ # def name_and_location
90
+ # "#{name} from #{location}"
91
+ # end
92
+ # end
93
+ #
94
+ # bob = Person.create! :name => "Bob Smith", :location => "New York City"
95
+ # bob.friendly_id #=> "bob-smith-from-new-york-city"
96
+ #
97
+ # FriendlyId refers to this internally as the "base" method.
98
+ #
99
+ # #### Uniqueness
100
+ #
101
+ # When you try to insert a record that would generate a duplicate friendly id,
102
+ # FriendlyId will append a UUID to the generated slug to ensure uniqueness:
103
+ #
104
+ # car = Car.create :title => "Peugeot 206"
105
+ # car2 = Car.create :title => "Peugeot 206"
106
+ #
107
+ # car.friendly_id #=> "peugeot-206"
108
+ # car2.friendly_id #=> "peugeot-206-f9f3789a-daec-4156-af1d-fab81aa16ee5"
109
+ #
110
+ # Previous versions of FriendlyId appended a numeric sequence to make slugs
111
+ # unique, but this was removed to simplify using FriendlyId in concurrent code.
112
+ #
113
+ # #### Candidates
114
+ #
115
+ # Since UUIDs are ugly, FriendlyId provides a "slug candidates" functionality to
116
+ # let you specify alternate slugs to use in the event the one you want to use is
117
+ # already taken. For example:
118
+ #
119
+ # class Restaurant < ActiveRecord::Base
120
+ # extend FriendlyId
121
+ # friendly_id :slug_candidates, use: :slugged
122
+ #
123
+ # # Try building a slug based on the following fields in
124
+ # # increasing order of specificity.
125
+ # def slug_candidates
126
+ # [
127
+ # :name,
128
+ # [:name, :city],
129
+ # [:name, :street, :city],
130
+ # [:name, :street_number, :street, :city]
131
+ # ]
132
+ # end
133
+ # end
134
+ #
135
+ # r1 = Restaurant.create! name: 'Plaza Diner', city: 'New Paltz'
136
+ # r2 = Restaurant.create! name: 'Plaza Diner', city: 'Kingston'
137
+ #
138
+ # r1.friendly_id #=> 'plaza-diner'
139
+ # r2.friendly_id #=> 'plaza-diner-kingston'
140
+ #
141
+ # To use candidates, make your FriendlyId base method return an array. The
142
+ # method need not be named `slug_candidates`; it can be anything you want. The
143
+ # array may contain any combination of symbols, strings, procs or lambdas and
144
+ # will be evaluated lazily and in order. If you include symbols, FriendlyId will
145
+ # invoke a method on your model class with the same name. Strings will be
146
+ # interpreted literally. Procs and lambdas will be called and their return values
147
+ # used as the basis of the friendly id. If none of the candidates can generate a
148
+ # unique slug, then FriendlyId will append a UUID to the first candidate as a
149
+ # last resort.
150
+ #
151
+ # #### Sequence Separator
152
+ #
153
+ # By default, FriendlyId uses a dash to separate the slug from a sequence.
154
+ #
155
+ # You can change this with the {FriendlyId::Slugged::Configuration#sequence_separator
156
+ # sequence_separator} configuration option.
157
+ #
158
+ # #### Providing Your Own Slug Processing Method
159
+ #
160
+ # You can override {FriendlyId::Slugged#normalize_friendly_id} in your model for
161
+ # total control over the slug format. It will be invoked for any generated slug,
162
+ # whether for a single slug or for slug candidates.
163
+ #
164
+ # #### Deciding When to Generate New Slugs
165
+ #
166
+ # As of FriendlyId 5.0, slugs are only generated when the `slug` field is nil. If
167
+ # you want a slug to be regenerated,set the slug field to nil:
168
+ #
169
+ # restaurant.friendly_id # joes-diner
170
+ # restaurant.name = "The Plaza Diner"
171
+ # restaurant.save!
172
+ # restaurant.friendly_id # joes-diner
173
+ # restaurant.slug = nil
174
+ # restaurant.save!
175
+ # restaurant.friendly_id # the-plaza-diner
176
+ #
177
+ # You can also override the
178
+ # {FriendlyId::Slugged#should_generate_new_friendly_id?} method, which lets you
179
+ # control exactly when new friendly ids are set:
180
+ #
181
+ # class Post < ActiveRecord::Base
182
+ # extend FriendlyId
183
+ # friendly_id :title, :use => :slugged
184
+ #
185
+ # def should_generate_new_friendly_id?
186
+ # title_changed?
187
+ # end
188
+ # end
189
+ #
190
+ # If you want to extend the default behavior but add your own conditions,
191
+ # don't forget to invoke `super` from your implementation:
192
+ #
193
+ # class Category < ActiveRecord::Base
194
+ # extend FriendlyId
195
+ # friendly_id :name, :use => :slugged
196
+ #
197
+ # def should_generate_new_friendly_id?
198
+ # name_changed? || super
199
+ # end
200
+ # end
201
+ #
202
+ # #### Locale-specific Transliterations
203
+ #
204
+ # Active Support's `parameterize` uses
205
+ # [transliterate](http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-transliterate),
206
+ # which in turn can use I18n's transliteration rules to consider the current
207
+ # locale when replacing Latin characters:
208
+ #
209
+ # # config/locales/de.yml
210
+ # de:
211
+ # i18n:
212
+ # transliterate:
213
+ # rule:
214
+ # ü: "ue"
215
+ # ö: "oe"
216
+ # etc...
217
+ #
218
+ # movie = Movie.create! :title => "Der Preis fürs Überleben"
219
+ # movie.slug #=> "der-preis-fuers-ueberleben"
220
+ #
221
+ # This functionality was in fact taken from earlier versions of FriendlyId.
222
+ #
223
+ # #### Gotchas: Common Problems
224
+ #
225
+ # FriendlyId uses a before_validation callback to generate and set the slug. This
226
+ # means that if you create two model instances before saving them, it's possible
227
+ # they will generate the same slug, and the second save will fail.
228
+ #
229
+ # This can happen in two fairly normal cases: the first, when a model using nested
230
+ # attributes creates more than one record for a model that uses friendly_id. The
231
+ # second, in concurrent code, either in threads or multiple processes.
232
+ #
233
+ # To solve the nested attributes issue, I recommend simply avoiding them when
234
+ # creating more than one nested record for a model that uses FriendlyId. See [this
235
+ # Github issue](https://github.com/norman/friendly_id/issues/185) for discussion.
236
+ #
237
+ # @guide end
239
238
  module Slugged
240
-
241
239
  # Sets up behavior and configuration options for FriendlyId's slugging
242
240
  # feature.
243
241
  def self.included(model_class)
244
242
  model_class.friendly_id_config.instance_eval do
245
243
  self.class.send :include, Configuration
246
- self.slug_generator_class ||= SlugGenerator
247
- defaults[:slug_column] ||= 'slug'
248
- defaults[:sequence_separator] ||= '-'
244
+ self.slug_generator_class ||= SlugGenerator
245
+ defaults[:slug_column] ||= "slug"
246
+ defaults[:sequence_separator] ||= "-"
249
247
  end
250
248
  model_class.before_validation :set_slug
251
249
  model_class.before_save :set_slug
@@ -1,3 +1,3 @@
1
1
  module FriendlyId
2
- VERSION = '5.4.2'.freeze
2
+ VERSION = "5.5.1".freeze
3
3
  end
data/lib/friendly_id.rb CHANGED
@@ -1,55 +1,53 @@
1
- # encoding: utf-8
2
- require 'active_record'
1
+ require "active_record"
3
2
  require "friendly_id/base"
4
3
  require "friendly_id/object_utils"
5
4
  require "friendly_id/configuration"
6
5
  require "friendly_id/finder_methods"
7
6
 
8
- =begin
9
-
10
- ## About FriendlyId
11
-
12
- FriendlyId is an add-on to Ruby's Active Record that allows you to replace ids
13
- in your URLs with strings:
14
-
15
- # without FriendlyId
16
- http://example.com/states/4323454
17
-
18
- # with FriendlyId
19
- http://example.com/states/washington
20
-
21
- It requires few changes to your application code and offers flexibility,
22
- performance and a well-documented codebase.
23
-
24
- ### Core Concepts
25
-
26
- #### Slugs
27
-
28
- The concept of *slugs* is at the heart of FriendlyId.
29
-
30
- A slug is the part of a URL which identifies a page using human-readable
31
- keywords, rather than an opaque identifier such as a numeric id. This can make
32
- your application more friendly both for users and search engines.
33
-
34
- #### Finders: Slugs Act Like Numeric IDs
35
-
36
- To the extent possible, FriendlyId lets you treat text-based identifiers like
37
- normal IDs. This means that you can perform finds with slugs just like you do
38
- with numeric ids:
39
-
40
- Person.find(82542335)
41
- Person.friendly.find("joe")
42
-
43
- =end
7
+ # @guide begin
8
+ #
9
+ # ## About FriendlyId
10
+ #
11
+ # FriendlyId is an add-on to Ruby's Active Record that allows you to replace ids
12
+ # in your URLs with strings:
13
+ #
14
+ # # without FriendlyId
15
+ # http://example.com/states/4323454
16
+ #
17
+ # # with FriendlyId
18
+ # http://example.com/states/washington
19
+ #
20
+ # It requires few changes to your application code and offers flexibility,
21
+ # performance and a well-documented codebase.
22
+ #
23
+ # ### Core Concepts
24
+ #
25
+ # #### Slugs
26
+ #
27
+ # The concept of *slugs* is at the heart of FriendlyId.
28
+ #
29
+ # A slug is the part of a URL which identifies a page using human-readable
30
+ # keywords, rather than an opaque identifier such as a numeric id. This can make
31
+ # your application more friendly both for users and search engines.
32
+ #
33
+ # #### Finders: Slugs Act Like Numeric IDs
34
+ #
35
+ # To the extent possible, FriendlyId lets you treat text-based identifiers like
36
+ # normal IDs. This means that you can perform finds with slugs just like you do
37
+ # with numeric ids:
38
+ #
39
+ # Person.find(82542335)
40
+ # Person.friendly.find("joe")
41
+ #
42
+ # @guide end
44
43
  module FriendlyId
45
-
46
- autoload :History, "friendly_id/history"
47
- autoload :Slug, "friendly_id/slug"
48
- autoload :SimpleI18n, "friendly_id/simple_i18n"
49
- autoload :Reserved, "friendly_id/reserved"
50
- autoload :Scoped, "friendly_id/scoped"
51
- autoload :Slugged, "friendly_id/slugged"
52
- autoload :Finders, "friendly_id/finders"
44
+ autoload :History, "friendly_id/history"
45
+ autoload :Slug, "friendly_id/slug"
46
+ autoload :SimpleI18n, "friendly_id/simple_i18n"
47
+ autoload :Reserved, "friendly_id/reserved"
48
+ autoload :Scoped, "friendly_id/scoped"
49
+ autoload :Slugged, "friendly_id/slugged"
50
+ autoload :Finders, "friendly_id/finders"
53
51
  autoload :SequentiallySlugged, "friendly_id/sequentially_slugged"
54
52
 
55
53
  # FriendlyId takes advantage of `extended` to do basic model setup, primarily
@@ -77,7 +75,7 @@ module FriendlyId
77
75
  def self.extended(model_class)
78
76
  return if model_class.respond_to? :friendly_id
79
77
  class << model_class
80
- alias relation_without_friendly_id relation
78
+ alias_method :relation_without_friendly_id, :relation
81
79
  end
82
80
  model_class.class_eval do
83
81
  extend Base
@@ -102,8 +100,8 @@ module FriendlyId
102
100
  # config.use :slugged
103
101
  # end
104
102
  def self.defaults(&block)
105
- @defaults = block if block_given?
106
- @defaults ||= ->(config) {config.use :reserved}
103
+ @defaults = block if block
104
+ @defaults ||= ->(config) { config.use :reserved }
107
105
  end
108
106
 
109
107
  # Set the ActiveRecord table name prefix to friendly_id_
@@ -1,4 +1,4 @@
1
- require 'rails/generators'
1
+ require "rails/generators"
2
2
  require "rails/generators/active_record"
3
3
 
4
4
  # This generator adds a migration for the {FriendlyId::History
@@ -6,21 +6,21 @@ require "rails/generators/active_record"
6
6
  class FriendlyIdGenerator < ActiveRecord::Generators::Base
7
7
  # ActiveRecord::Generators::Base inherits from Rails::Generators::NamedBase which requires a NAME parameter for the
8
8
  # new table name. Our generator always uses 'friendly_id_slugs', so we just set a random name here.
9
- argument :name, type: :string, default: 'random_name'
9
+ argument :name, type: :string, default: "random_name"
10
10
 
11
- class_option :'skip-migration', :type => :boolean, :desc => "Don't generate a migration for the slugs table"
12
- class_option :'skip-initializer', :type => :boolean, :desc => "Don't generate an initializer"
11
+ class_option :'skip-migration', type: :boolean, desc: "Don't generate a migration for the slugs table"
12
+ class_option :'skip-initializer', type: :boolean, desc: "Don't generate an initializer"
13
13
 
14
- source_root File.expand_path('../../friendly_id', __FILE__)
14
+ source_root File.expand_path("../../friendly_id", __FILE__)
15
15
 
16
16
  # Copies the migration template to db/migrate.
17
17
  def copy_files
18
- return if options['skip-migration']
19
- migration_template 'migration.rb', 'db/migrate/create_friendly_id_slugs.rb'
18
+ return if options["skip-migration"]
19
+ migration_template "migration.rb", "db/migrate/create_friendly_id_slugs.rb"
20
20
  end
21
21
 
22
22
  def create_initializer
23
- return if options['skip-initializer']
24
- copy_file 'initializer.rb', 'config/initializers/friendly_id.rb'
23
+ return if options["skip-initializer"]
24
+ copy_file "initializer.rb", "config/initializers/friendly_id.rb"
25
25
  end
26
26
  end