mongoid-slug 6.0.0 → 6.0.1

Sign up to get free protection for your applications and to get access to all the features.
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.