mongoid-slug 6.0.0 → 6.0.1

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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +20 -20
  3. data/README.md +361 -336
  4. data/lib/mongoid/slug.rb +328 -328
  5. data/lib/mongoid/slug/criteria.rb +107 -107
  6. data/lib/mongoid/slug/{index.rb → index_builder.rb} +67 -45
  7. data/lib/mongoid/slug/railtie.rb +9 -9
  8. data/lib/mongoid/slug/slug_id_strategy.rb +3 -3
  9. data/lib/mongoid/slug/unique_slug.rb +173 -173
  10. data/lib/mongoid/slug/version.rb +5 -5
  11. data/lib/mongoid_slug.rb +2 -2
  12. data/lib/tasks/mongoid_slug.rake +15 -19
  13. data/spec/models/alias.rb +6 -6
  14. data/spec/models/article.rb +9 -9
  15. data/spec/models/artist.rb +8 -8
  16. data/spec/models/artwork.rb +10 -10
  17. data/spec/models/author.rb +15 -15
  18. data/spec/models/author_polymorphic.rb +15 -15
  19. data/spec/models/book.rb +12 -12
  20. data/spec/models/book_polymorphic.rb +12 -12
  21. data/spec/models/caption.rb +17 -17
  22. data/spec/models/entity.rb +11 -11
  23. data/spec/models/friend.rb +7 -7
  24. data/spec/models/incorrect_slug_persistence.rb +9 -9
  25. data/spec/models/integer_id.rb +9 -9
  26. data/spec/models/magazine.rb +7 -7
  27. data/spec/models/page.rb +9 -9
  28. data/spec/models/page_localize.rb +9 -9
  29. data/spec/models/page_slug_localized.rb +9 -9
  30. data/spec/models/page_slug_localized_custom.rb +10 -10
  31. data/spec/models/page_slug_localized_history.rb +9 -9
  32. data/spec/models/partner.rb +7 -7
  33. data/spec/models/person.rb +12 -12
  34. data/spec/models/relationship.rb +8 -8
  35. data/spec/models/string_id.rb +9 -9
  36. data/spec/models/subject.rb +7 -7
  37. data/spec/models/without_slug.rb +5 -5
  38. data/spec/mongoid/criteria_spec.rb +207 -207
  39. data/spec/mongoid/index_builder_spec.rb +105 -0
  40. data/spec/mongoid/slug_spec.rb +1175 -1169
  41. data/spec/shared/indexes.rb +41 -41
  42. data/spec/spec_helper.rb +61 -61
  43. data/spec/tasks/mongoid_slug_rake_spec.rb +73 -73
  44. metadata +31 -32
  45. data/spec/mongoid/index_spec.rb +0 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf9ad642da6118dcc879edd3c4b6f43adf2b110e422d691926984ffb743f0dcf
4
- data.tar.gz: 800d4c721c01fb89267218aaeff2c5a8d91a906f8587c87aa3680d774011180b
3
+ metadata.gz: 54274387f9a202810aefa5b3b19c90990636d6076cbc6591cf46129986b4b5e4
4
+ data.tar.gz: 557ba29c3dfaa615f7e926ba223bb3390e930a52ed559baf33b0517cf224aaa8
5
5
  SHA512:
6
- metadata.gz: 8bb6300dd08988c87f922e5cfc308de3ea428a8730a75d9b2c261814cb1a8568ad266b94e8358d710602af131166dbf063ad1e163eca2a2d31108be7d147456d
7
- data.tar.gz: 36dd52ca7e37b0e57cd4241ab616a20892688dfb4e79af8e02ada7f7802c30b158bb28b5594337eded30c47de948e20e1e40da69bc84ef2398e463d738c63188
6
+ metadata.gz: 11a15aec160529e61f5e6fe9636d9fded847d12ec08fe50e6c67997aca86fed844f42264962c65999e862b7a73ba3d41c337c7fae492e8c91999efbd889ea502
7
+ data.tar.gz: ff604c15c46fa831bb648906b802cc8e93d13363207fc3a121b7b1c3e4ef3ccb46305f630507ded0e24ad07d70069e4e70ae3185d022267e5ba4c42b53381b44
data/LICENSE CHANGED
@@ -1,20 +1,20 @@
1
- Copyright (c) 2010-2017 Hakan Ensari & Contributors
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
+ Copyright (c) 2010-2017 Hakan Ensari & Contributors
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,336 +1,361 @@
1
- Mongoid Slug
2
- ============
3
-
4
- Mongoid Slug generates a URL slug or permalink based on one or more fields in a Mongoid model. It sits idly on top of [stringex](https://github.com/rsl/stringex), supporting non-Latin characters.
5
-
6
- [![Build Status](https://secure.travis-ci.org/mongoid/mongoid-slug.svg)](http://travis-ci.org/mongoid/mongoid-slug)
7
- [![Gem Version](https://badge.fury.io/rb/mongoid-slug.svg)](http://badge.fury.io/rb/mongoid-slug)
8
- [![Dependency Status](https://gemnasium.com/mongoid/mongoid-slug.svg)](https://gemnasium.com/mongoid/mongoid-slug)
9
- [![Code Climate](https://codeclimate.com/github/mongoid/mongoid-slug.svg)](https://codeclimate.com/github/mongoid/mongoid-slug)
10
-
11
- ### Installation
12
-
13
- Add to your Gemfile:
14
-
15
- ```ruby
16
- gem 'mongoid-slug'
17
- ```
18
-
19
- ### Usage
20
-
21
- ### Set Up a Slug
22
-
23
- ```ruby
24
- class Book
25
- include Mongoid::Document
26
- include Mongoid::Slug
27
-
28
- field :title
29
- slug :title
30
- end
31
- ```
32
-
33
- ### Find a Document by its Slug
34
-
35
- ```ruby
36
- # GET /books/a-thousand-plateaus
37
- book = Book.find params[:book_id]
38
- ```
39
-
40
- Mongoid Slug will attempt to determine whether you want to find using the `slugs` field or the `_id` field by inspecting the supplied parameters.
41
-
42
- * Mongoid Slug will perform a find based on `slugs` only if all arguments passed to `find` are of the type `String`.
43
- * If your document uses `BSON::ObjectId` identifiers, and all arguments look like valid `BSON::ObjectId`, then Mongoid Slug will perform a find based on `_id`.
44
- * If your document uses any other type of identifiers, and all arguments passed to `find` are of the same type, then Mongoid Slug will perform a find based on `_id`.
45
- * If your document uses `String` identifiers and you want to be able find by slugs or ids, to get the correct behaviour, you should add a `slug_id_strategy` option to your `_id` field definition. This option should return something that responds to `call` (a callable) and takes one string argument, e.g. a lambda. This callable must return true if the string looks like one of your ids.
46
-
47
- ```ruby
48
- Book.fields['_id'].type
49
- => String
50
- book = Book.find 'a-thousand-plateaus' # Finds by slugs
51
- => ...
52
-
53
- class Post
54
- include Mongoid::Document
55
- include Mongoid::Slug
56
-
57
- field :_id, type: String, slug_id_strategy: lambda { |id| id.start_with?('...') }
58
-
59
- field :name
60
- slug :name, history: true
61
- end
62
-
63
- Post.fields['_id'].type
64
- => String
65
- post = Post.find 'a-thousand-plateaus' # Finds by slugs
66
- => ...
67
- post = Post.find '50b1386a0482939864000001' # Finds by bson ids
68
- => ...
69
- ```
70
- [Examine slug.rb](lib/mongoid/slug.rb) for all available options.
71
-
72
- ### Updating Existing Records
73
-
74
- To set slugs for existing records run following rake task:
75
-
76
- ```ruby
77
- rake mongoid_slug:set
78
- ```
79
-
80
- You can pass model names as an option for which you want to set slugs:
81
-
82
- ```ruby
83
- rake mongoid_slug:set[Model1,Model2]
84
- ```
85
-
86
- ### Nil Slugs
87
-
88
- Empty slugs are possible and generate a `nil` value for the `_slugs` field. In the `Post` example above, a blank post `name` will cause the document record not to contain a `_slugs` field in the database. The default `_slugs` index is `sparse`, allowing that. If you wish to change this behavior add a custom `validates_presence_of :_slugs` validator to the document or change the database index to `sparse: false`.
89
-
90
- ### Custom Slug Generation
91
-
92
- By default Mongoid Slug generates slugs with stringex. If this is not desired you can define your own slug generator.
93
-
94
- There are two ways to define slug generator.
95
-
96
- #### Globally
97
-
98
- Configure a block in `config/initializers/mongoid_slug.rb` as follows:
99
-
100
- ```ruby
101
- Mongoid::Slug.configure do |c|
102
- # create a block that takes the current object as an argument and return the slug
103
- c.slug = proc { |cur_obj|
104
- cur_object.slug_builder.to_url
105
- }
106
- end
107
- ```
108
-
109
- #### On Model
110
-
111
- ```ruby
112
- class Caption
113
- include Mongoid::Document
114
- include Mongoid::Slug
115
-
116
- # create a block that takes the current object as an argument and returns the slug
117
- slug do |cur_object|
118
- cur_object.slug_builder.to_url
119
- end
120
- end
121
- ```
122
-
123
- The `to_url` method comes from [stringex](https://github.com/rsl/stringex).
124
-
125
- You can define a slug builder globally and/or override it per model.
126
-
127
- ### Scoping
128
-
129
- To scope a slug by a reference association, pass `:scope`:
130
-
131
- ```ruby
132
- class Company
133
- include Mongoid::Document
134
-
135
- references_many :employees
136
- end
137
-
138
- class Employee
139
- include Mongoid::Document
140
- include Mongoid::Slug
141
-
142
- field :name
143
- referenced_in :company
144
-
145
- slug :name, scope: :company
146
- end
147
- ```
148
-
149
- In this example, if you create an employee without associating it with any company, the scope will fall back to the root employees collection.
150
-
151
- Currently, if you have an irregular association name, you **must** specify the `:inverse_of` option on the other side of the assocation.
152
-
153
- Embedded objects are automatically scoped by their parent.
154
-
155
- Note that the unique index on the `Employee` collection in this example is derived from the `scope` value and is `{ _slugs: 1, company_id: 1}`. Therefore `:company` must be `referenced_in` above the definition of `slug` or it will not be able to resolve the association and mistakenly create a `{ _slugs: 1, company: 1}` index. An alternative is to scope to the field itself as follows:
156
-
157
- ```ruby
158
- class Employee
159
- include Mongoid::Document
160
- include Mongoid::Slug
161
-
162
- field :name
163
- field :company_id
164
-
165
- slug :name, scope: :company_id
166
- end
167
- ```
168
-
169
- ### Limit Slug Length
170
-
171
- MongoDB has a default limit around 1KB to the size of the index keys and will raise error 17280, `key too large to index` when trying to create a record that causes an index key to exceed that limit. By default slugs are of the form `text[-number]` and the text portion is limited in size to `Mongoid::Slug::MONGO_INDEX_KEY_LIMIT_BYTES - 32` bytes. You can change this limit with `max_length` or set it to `nil` if you're running MongoDB with [failIndexKeyTooLong](https://docs.mongodb.org/manual/reference/parameters/#param.failIndexKeyTooLong) set to `false`.
172
-
173
- ```ruby
174
- class Company
175
- include Mongoid::Document
176
- include Mongoid::Slug
177
-
178
- field :name
179
-
180
- slug :name, max_length: 24
181
- end
182
- ```
183
-
184
- ### Optionally Find and Create Slugs per Model Type
185
-
186
- By default when using STI, the scope will be around the super-class.
187
-
188
- ```ruby
189
- class Book
190
- include Mongoid::Document
191
- include Mongoid::Slug
192
- field :title
193
-
194
- slug :title, history: true
195
- embeds_many :subjects
196
- has_many :authors
197
- end
198
-
199
- class ComicBook < Book
200
- end
201
-
202
- book = Book.create(title: 'Anti Oedipus')
203
- comic_book = ComicBook.create(title: 'Anti Oedipus')
204
- comic_book.slugs.should_not eql(book.slugs)
205
- ```
206
-
207
- If you want the scope to be around the subclass, then set the option `by_model_type: true`.
208
-
209
- ```ruby
210
- class Book
211
- include Mongoid::Document
212
- include Mongoid::Slug
213
- field :title
214
-
215
- slug :title, history: true, by_model_type: true
216
- embeds_many :subjects
217
- has_many :authors
218
- end
219
-
220
- class ComicBook < Book
221
- end
222
-
223
- book = Book.create(title: 'Anti Oedipus')
224
- comic_book = ComicBook.create(title: 'Anti Oedipus')
225
- comic_book.slugs.should eql(book.slugs)
226
- ```
227
-
228
- ### History
229
-
230
- Enable slug history tracking by setting `history: true`.
231
-
232
- ```ruby
233
- class Page
234
- include Mongoid::Document
235
- include Mongoid::Slug
236
-
237
- field :title
238
-
239
- slug :title, history: true
240
- end
241
- ```
242
-
243
- The document will then be returned for any of the saved slugs:
244
-
245
- ```ruby
246
- page = Page.new title: "Home"
247
- page.save
248
- page.update_attributes title: "Welcome"
249
-
250
- Page.find("welcome") == Page.find("home") # => true
251
- ```
252
-
253
- ### Reserved Slugs
254
-
255
- Pass words you do not want to be slugged using the `reserve` option:
256
-
257
- ```ruby
258
- class Friend
259
- include Mongoid::Document
260
-
261
- field :name
262
- slug :name, reserve: ['admin', 'root']
263
- end
264
-
265
- friend = Friend.create name: 'admin'
266
- Friend.find('admin') # => nil
267
- friend.slug # => 'admin-1'
268
- ```
269
-
270
- When reserved words are not specified, the words 'new' and 'edit' are considered reserved by default.
271
- Specifying an array of custom reserved words will overwrite these defaults.
272
-
273
- ### Localize Slugs
274
-
275
- The slugs can be localized:
276
-
277
- ```ruby
278
- class PageSlugLocalize
279
- include Mongoid::Document
280
- include Mongoid::Slug
281
-
282
- field :title, localize: true
283
- slug :title, localize: true
284
- end
285
- ```
286
-
287
- This feature is built upon Mongoid localized fields, so fallbacks and localization works as documented in the Mongoid manual.
288
-
289
- ### Custom Find Strategies
290
-
291
- By default find will search for the document by the id field if the provided id looks like a `BSON::ObjectId`, and it will otherwise find by the _slugs field. However, custom strategies can ovveride the default behavior, like e.g:
292
-
293
- ```ruby
294
- module Mongoid::Slug::UuidIdStrategy
295
- def self.call id
296
- id =~ /\A([0-9a-fA-F]){8}-(([0-9a-fA-F]){4}-){3}([0-9a-fA-F]){12}\z/
297
- end
298
- end
299
- ```
300
-
301
- Use a custom strategy by adding the `slug_id_strategy` annotation to the `_id` field:
302
-
303
- ```ruby
304
- class Entity
305
- include Mongoid::Document
306
- include Mongoid::Slug
307
-
308
- field :_id, type: String, slug_id_strategy: UuidIdStrategy
309
-
310
- field :user_edited_variation
311
- slug :user_edited_variation, history: true
312
- end
313
- ```
314
-
315
- ### Adhoc Checking Whether a Slug is Unique
316
-
317
- Lets say you want to have a auto-suggest function on your GUI that could provide a preview of what the url or slug could be before the form to create the record was submitted.
318
-
319
- You can use the UniqueSlug class in your server side code to do this, e.g.
320
-
321
- ```ruby
322
- title = params[:title]
323
- unique = Mongoid::Slug::UniqueSlug.new(Book.new).find_unique(title)
324
- ...
325
- # return some representation of unique
326
- ```
327
-
328
- Contributing
329
- ------------
330
-
331
- Mongoid-slug is work of [many of contributors](https://github.com/mongoid/mongoid-slug/graphs/contributors). You're encouraged to submit [pull requests](https://github.com/mongoid/mongoid-slug/pulls), [propose features, ask questions and discuss issues](https://github.com/mongoid/mongoid-slug/issues). See [CONTRIBUTING](CONTRIBUTING.md) for details.
332
-
333
- Copyright & License
334
- -------------------
335
-
336
- Copyright (c) 2010-2017 Hakan Ensari & Contributors, see [LICENSE](LICENSE) for details.
1
+ Mongoid Slug
2
+ ============
3
+
4
+ Mongoid Slug generates a URL slug or permalink based on one or more fields in a Mongoid model.
5
+ It sits idly on top of [stringex](https://github.com/rsl/stringex), supporting non-Latin characters.
6
+
7
+ [![Build Status](https://github.com/mongoid/mongoid-slug/actions/workflows/test.yml/badge.svg?query=branch%3Amaster)](https://github.com/mongoid/mongoid-slug/actions/workflows/test.ym?query=branch%3Amaster)
8
+ [![Gem Version](https://badge.fury.io/rb/mongoid-slug.svg)](http://badge.fury.io/rb/mongoid-slug)
9
+ [![Code Climate](https://codeclimate.com/github/mongoid/mongoid-slug.svg)](https://codeclimate.com/github/mongoid/mongoid-slug)
10
+
11
+ ### Installation
12
+
13
+ Add to your Gemfile:
14
+
15
+ ```ruby
16
+ gem 'mongoid-slug'
17
+ ```
18
+
19
+ ### Usage
20
+
21
+ ### Set Up a Slug
22
+
23
+ ```ruby
24
+ class Book
25
+ include Mongoid::Document
26
+ include Mongoid::Slug
27
+
28
+ field :title
29
+ slug :title
30
+ end
31
+ ```
32
+
33
+ ### Find a Document by its Slug
34
+
35
+ ```ruby
36
+ # GET /books/a-thousand-plateaus
37
+ book = Book.find params[:book_id]
38
+ ```
39
+
40
+ Mongoid Slug will attempt to determine whether you want to find using the `slugs` field or the `_id` field by inspecting the supplied parameters.
41
+
42
+ * Mongoid Slug will perform a find based on `slugs` only if all arguments passed to `find` are of the type `String`.
43
+ * If your document uses `BSON::ObjectId` identifiers, and all arguments look like valid `BSON::ObjectId`, then Mongoid Slug will perform a find based on `_id`.
44
+ * If your document uses any other type of identifiers, and all arguments passed to `find` are of the same type, then Mongoid Slug will perform a find based on `_id`.
45
+ * If your document uses `String` identifiers and you want to be able find by slugs or ids, to get the correct behaviour, you should add a `slug_id_strategy` option to your `_id` field definition. This option should return something that responds to `call` (a callable) and takes one string argument, e.g. a lambda. This callable must return true if the string looks like one of your ids.
46
+
47
+ ```ruby
48
+ Book.fields['_id'].type
49
+ => String
50
+
51
+ book = Book.find 'a-thousand-plateaus' # Finds by slugs
52
+ => ...
53
+
54
+ class Post
55
+ include Mongoid::Document
56
+ include Mongoid::Slug
57
+
58
+ field :_id, type: String, slug_id_strategy: lambda { |id| id.start_with?('...') }
59
+
60
+ field :name
61
+ slug :name, history: true
62
+ end
63
+
64
+ Post.fields['_id'].type
65
+ => String
66
+
67
+ post = Post.find 'a-thousand-plateaus' # Finds by slugs
68
+ => ...
69
+
70
+ post = Post.find '50b1386a0482939864000001' # Finds by bson ids
71
+ => ...
72
+ ```
73
+ [Examine slug.rb](lib/mongoid/slug.rb) for all available options.
74
+
75
+ ### Updating Existing Records
76
+
77
+ To set slugs for existing records run following rake task:
78
+
79
+ ```ruby
80
+ rake mongoid_slug:set
81
+ ```
82
+
83
+ You can pass model names as an option for which you want to set slugs:
84
+
85
+ ```ruby
86
+ rake mongoid_slug:set[Model1,Model2]
87
+ ```
88
+
89
+ ### Nil Slugs
90
+
91
+ Empty slugs are possible and generate a `nil` value for the `_slugs` field. In the `Post` example above, a blank post `name` will cause the document record not to contain a `_slugs` field in the database. The default `_slugs` index is `sparse`, allowing that. If you wish to change this behavior add a custom `validates_presence_of :_slugs` validator to the document or change the database index to `sparse: false`.
92
+
93
+ ### Custom Slug Generation
94
+
95
+ By default Mongoid Slug generates slugs with stringex. If this is not desired you can define your own slug generator.
96
+
97
+ There are two ways to define slug generator.
98
+
99
+ #### Globally
100
+
101
+ Configure a block in `config/initializers/mongoid_slug.rb` as follows:
102
+
103
+ ```ruby
104
+ Mongoid::Slug.configure do |c|
105
+ # create a block that takes the current object as an argument and return the slug
106
+ c.slug = proc { |cur_obj|
107
+ cur_object.slug_builder.to_url
108
+ }
109
+ end
110
+ ```
111
+
112
+ #### On Model
113
+
114
+ ```ruby
115
+ class Caption
116
+ include Mongoid::Document
117
+ include Mongoid::Slug
118
+
119
+ # create a block that takes the current object as an argument and returns the slug
120
+ slug do |cur_object|
121
+ cur_object.slug_builder.to_url
122
+ end
123
+ end
124
+ ```
125
+
126
+ The `to_url` method comes from [stringex](https://github.com/rsl/stringex).
127
+
128
+ You can define a slug builder globally and/or override it per model.
129
+
130
+ ### Scoping
131
+
132
+ To scope a slug by a reference association, pass `:scope`:
133
+
134
+ ```ruby
135
+ class Company
136
+ include Mongoid::Document
137
+
138
+ references_many :employees
139
+ end
140
+
141
+ class Employee
142
+ include Mongoid::Document
143
+ include Mongoid::Slug
144
+
145
+ field :name
146
+ referenced_in :company
147
+
148
+ slug :name, scope: :company
149
+ end
150
+ ```
151
+
152
+ In this example, if you create an employee without associating it with any company, the scope will fall back to the root employees collection.
153
+
154
+ Currently, if you have an irregular association name, you **must** specify the `:inverse_of` option on the other side of the assocation.
155
+
156
+ Embedded objects are automatically scoped by their parent.
157
+
158
+ Note that the unique index on the `Employee` collection in this example is derived from the `scope` value and is `{ _slugs: 1, company_id: 1}`. Therefore `:company` must be `referenced_in` above the definition of `slug` or it will not be able to resolve the association and mistakenly create a `{ _slugs: 1, company: 1}` index. An alternative is to scope to the field itself as follows:
159
+
160
+ ```ruby
161
+ class Employee
162
+ include Mongoid::Document
163
+ include Mongoid::Slug
164
+
165
+ field :name
166
+ field :company_id
167
+
168
+ slug :name, scope: :company_id
169
+ end
170
+ ```
171
+
172
+ ### Limit Slug Length
173
+
174
+ MongoDB has a default limit around 1KB to the size of the index keys and will raise error 17280, `key too large to index` when trying to create a record that causes an index key to exceed that limit. By default slugs are of the form `text[-number]` and the text portion is limited in size to `Mongoid::Slug::MONGO_INDEX_KEY_LIMIT_BYTES - 32` bytes. You can change this limit with `max_length` or set it to `nil` if you're running MongoDB with [failIndexKeyTooLong](https://docs.mongodb.org/manual/reference/parameters/#param.failIndexKeyTooLong) set to `false`.
175
+
176
+ ```ruby
177
+ class Company
178
+ include Mongoid::Document
179
+ include Mongoid::Slug
180
+
181
+ field :name
182
+
183
+ slug :name, max_length: 24
184
+ end
185
+ ```
186
+
187
+ ### Optionally Find and Create Slugs per Model Type
188
+
189
+ By default when using STI, the scope will be around the super-class.
190
+
191
+ ```ruby
192
+ class Book
193
+ include Mongoid::Document
194
+ include Mongoid::Slug
195
+ field :title
196
+
197
+ slug :title, history: true
198
+ embeds_many :subjects
199
+ has_many :authors
200
+ end
201
+
202
+ class ComicBook < Book
203
+ end
204
+
205
+ book = Book.create(title: 'Anti Oedipus')
206
+ comic_book = ComicBook.create(title: 'Anti Oedipus')
207
+ comic_book.slugs.should_not eql(book.slugs)
208
+ ```
209
+
210
+ If you want the scope to be around the subclass, then set the option `by_model_type: true`.
211
+
212
+ ```ruby
213
+ class Book
214
+ include Mongoid::Document
215
+ include Mongoid::Slug
216
+ field :title
217
+
218
+ slug :title, history: true, by_model_type: true
219
+ embeds_many :subjects
220
+ has_many :authors
221
+ end
222
+
223
+ class ComicBook < Book
224
+ end
225
+
226
+ book = Book.create(title: 'Anti Oedipus')
227
+ comic_book = ComicBook.create(title: 'Anti Oedipus')
228
+ comic_book.slugs.should eql(book.slugs)
229
+ ```
230
+
231
+ ### History
232
+
233
+ Enable slug history tracking by setting `history: true`.
234
+
235
+ ```ruby
236
+ class Page
237
+ include Mongoid::Document
238
+ include Mongoid::Slug
239
+
240
+ field :title
241
+
242
+ slug :title, history: true
243
+ end
244
+ ```
245
+
246
+ The document will then be returned for any of the saved slugs:
247
+
248
+ ```ruby
249
+ page = Page.new title: "Home"
250
+ page.save
251
+ page.update_attributes title: "Welcome"
252
+
253
+ Page.find("welcome") == Page.find("home") # => true
254
+ ```
255
+
256
+ ### Reserved Slugs
257
+
258
+ Pass words you do not want to be slugged using the `reserve` option:
259
+
260
+ ```ruby
261
+ class Friend
262
+ include Mongoid::Document
263
+
264
+ field :name
265
+ slug :name, reserve: ['admin', 'root']
266
+ end
267
+
268
+ friend = Friend.create name: 'admin'
269
+ Friend.find('admin') # => nil
270
+ friend.slug # => 'admin-1'
271
+ ```
272
+
273
+ When reserved words are not specified, the words 'new' and 'edit' are considered reserved by default.
274
+ Specifying an array of custom reserved words will overwrite these defaults.
275
+
276
+ ### Localize Slugs
277
+
278
+ The slugs can be localized. This feature is built upon Mongoid localized fields,
279
+ so fallbacks and localization works as documented in the Mongoid manual.
280
+
281
+ ```ruby
282
+ class PageSlugLocalize
283
+ include Mongoid::Document
284
+ include Mongoid::Slug
285
+
286
+ field :title, localize: true
287
+ slug :title, localize: true
288
+ end
289
+ ```
290
+
291
+ By specifying `localize: true`, the slug index will be created on the
292
+ [I18n.default_locale](http://guides.rubyonrails.org/i18n.html#the-public-i18n-api) field only.
293
+ For example, if `I18n.default_locale` is `:en`, the index will be generated as follows:
294
+
295
+ ```ruby
296
+ slug :title, localize: true
297
+
298
+ # The following indexes is auto-generated:
299
+ index({ '_slugs.en' => 1 }, { unique: true, sparse: true })
300
+ ```
301
+
302
+ If you are supporting multiple locales, you may specify the list of locales on which
303
+ to create indexes as an `Array`.
304
+
305
+ ```ruby
306
+ slug :title, localize: [:fr, :es, :de]
307
+
308
+ # The following indexes are auto-generated:
309
+ index({ '_slugs.fr' => 1 }, { unique: true, sparse: true })
310
+ index({ '_slugs.es' => 1 }, { unique: true, sparse: true })
311
+ index({ '_slugs.de' => 1 }, { unique: true, sparse: true })
312
+ ```
313
+
314
+ ### Custom Find Strategies
315
+
316
+ By default find will search for the document by the id field if the provided id looks like a `BSON::ObjectId`, and it will otherwise find by the _slugs field. However, custom strategies can ovveride the default behavior, like e.g:
317
+
318
+ ```ruby
319
+ module Mongoid::Slug::UuidIdStrategy
320
+ def self.call id
321
+ id =~ /\A([0-9a-fA-F]){8}-(([0-9a-fA-F]){4}-){3}([0-9a-fA-F]){12}\z/
322
+ end
323
+ end
324
+ ```
325
+
326
+ Use a custom strategy by adding the `slug_id_strategy` annotation to the `_id` field:
327
+
328
+ ```ruby
329
+ class Entity
330
+ include Mongoid::Document
331
+ include Mongoid::Slug
332
+
333
+ field :_id, type: String, slug_id_strategy: UuidIdStrategy
334
+
335
+ field :user_edited_variation
336
+ slug :user_edited_variation, history: true
337
+ end
338
+ ```
339
+
340
+ ### Adhoc Checking Whether a Slug is Unique
341
+
342
+ Lets say you want to have a auto-suggest function on your GUI that could provide a preview of what the url or slug could be before the form to create the record was submitted.
343
+
344
+ You can use the UniqueSlug class in your server side code to do this, e.g.
345
+
346
+ ```ruby
347
+ title = params[:title]
348
+ unique = Mongoid::Slug::UniqueSlug.new(Book.new).find_unique(title)
349
+ ...
350
+ # return some representation of unique
351
+ ```
352
+
353
+ Contributing
354
+ ------------
355
+
356
+ Mongoid-slug is work of [many of contributors](https://github.com/mongoid/mongoid-slug/graphs/contributors). You're encouraged to submit [pull requests](https://github.com/mongoid/mongoid-slug/pulls), [propose features, ask questions and discuss issues](https://github.com/mongoid/mongoid-slug/issues). See [CONTRIBUTING](CONTRIBUTING.md) for details.
357
+
358
+ Copyright & License
359
+ -------------------
360
+
361
+ Copyright (c) 2010-2017 Hakan Ensari & Contributors, see [LICENSE](LICENSE) for details.