mongoid-slug 4.0.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +13 -5
  2. data/LICENSE +1 -1
  3. data/README.md +18 -18
  4. data/lib/mongoid/slug.rb +48 -44
  5. data/lib/mongoid/slug/criteria.rb +14 -11
  6. data/lib/mongoid/slug/index.rb +5 -8
  7. data/lib/mongoid/slug/paranoia.rb +0 -2
  8. data/lib/mongoid/slug/slug_id_strategy.rb +1 -1
  9. data/lib/mongoid/slug/unique_slug.rb +27 -29
  10. data/lib/mongoid/slug/version.rb +1 -1
  11. data/spec/models/alias.rb +2 -2
  12. data/spec/models/article.rb +1 -1
  13. data/spec/models/author.rb +3 -3
  14. data/spec/models/author_polymorphic.rb +3 -3
  15. data/spec/models/book.rb +1 -1
  16. data/spec/models/book_polymorphic.rb +1 -1
  17. data/spec/models/caption.rb +1 -1
  18. data/spec/models/entity.rb +2 -2
  19. data/spec/models/friend.rb +2 -2
  20. data/spec/models/incorrect_slug_persistence.rb +5 -5
  21. data/spec/models/integer_id.rb +1 -1
  22. data/spec/models/magazine.rb +1 -1
  23. data/spec/models/page.rb +3 -3
  24. data/spec/models/page_localize.rb +3 -3
  25. data/spec/models/page_slug_localized.rb +3 -3
  26. data/spec/models/page_slug_localized_custom.rb +0 -1
  27. data/spec/models/page_slug_localized_history.rb +3 -3
  28. data/spec/models/paranoid_document.rb +1 -1
  29. data/spec/models/paranoid_permanent.rb +1 -1
  30. data/spec/models/partner.rb +1 -1
  31. data/spec/models/person.rb +2 -2
  32. data/spec/models/relationship.rb +1 -1
  33. data/spec/models/string_id.rb +1 -1
  34. data/spec/models/subject.rb +1 -1
  35. data/spec/models/without_slug.rb +1 -1
  36. data/spec/mongoid/criteria_spec.rb +109 -109
  37. data/spec/mongoid/index_spec.rb +12 -14
  38. data/spec/mongoid/paranoia_spec.rb +78 -90
  39. data/spec/mongoid/slug_spec.rb +493 -492
  40. data/spec/shared/indexes.rb +13 -13
  41. data/spec/spec_helper.rb +18 -14
  42. metadata +51 -26
  43. data/spec/mongoid/slug_spec.rb.b00 +0 -1101
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ae9c5f1b269558e56ea27b2c659cc14d4670b886
4
- data.tar.gz: bd270a6a2320c369d822dfb7836ea2a13d85db01
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NzVhMTg3OTVmNzYyZDVmNWQ1MGQxYTNiMDYyZDUzMDhkMTFiNjNkOA==
5
+ data.tar.gz: !binary |-
6
+ MDNjMmJjZTI4MDE3Njk1NThhYjg4ZTZjNmEwYzE4NzVkMjA3ZTUwNg==
5
7
  SHA512:
6
- metadata.gz: 9c662ebc338efef83a34c6d509c2c012e1404b50ddf9337a8570e27c76ef8ee5e8c2e0eae6ba871bcd669042fee6b3f69576213073726a5f45f5be2e84c9eaac
7
- data.tar.gz: 63d767317c4169410246110ea16942ced927e773c7ec94ea83bef62a1d2004a46fa2ce3c9d65ea94a5ef63fad6b2e0f3fe391e4af162a7a5a67dd112a9593a36
8
+ metadata.gz: !binary |-
9
+ NWIzMWQzYTFlNTNhNDcwY2IwN2RhM2M0M2Q5OGVkNTg1MjUzOTM1ODA5N2Rh
10
+ ZTA0NjQ0ODk0MGI5MDMzNmM4Y2I0ZDAzZWIxYzM3ZmVjOTZiYTA3NGJhZjJi
11
+ YmQyOWQxZjkwZmVmYTBkOWM4MTMxMTAzYjRhZDc2MDdhMDBiYzA=
12
+ data.tar.gz: !binary |-
13
+ MTBkMDU5NDRlYjkxY2MyNDdjMTI1OWY4NThkYTkyNTRmMzUyZmY2ZDU4ODVl
14
+ MjU2YjNjMTRkZThiNmU3OWRmNGQ0ZTEyZTkxZTFkNDQ2ZTJkMmI2YjJmMTgx
15
+ OWQxNDEwYTQ5OTYzYzI3ZDk3MTlkMWFlNThjNTcyODJmZTI0Yjc=
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010-2012 Hakan Ensari
1
+ Copyright (c) 2010-2015 Hakan Ensari & Contributors
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,14 +1,12 @@
1
- *IMPORTANT:* If you are upgrading to Mongoid Slug 1.0.0 please migrate in accordance with the instructions in https://github.com/digitalplaywright/mongoid-slug/wiki/How-to-upgrade-to-1.0.0-or-newer.
2
- Mongoid Slug 1.0.0 stores the slugs in a single field _slugs of array type, and all previous slugs must be migrated.
3
-
4
1
  Mongoid Slug
5
2
  ============
6
3
 
7
- Mongoid Slug generates a URL slug or permalink based on one or more fields in a
8
- Mongoid model. It sits idly on top of [stringex] [1], supporting non-Latin
9
- characters.
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.
10
5
 
11
- [![Build Status](https://secure.travis-ci.org/digitalplaywright/mongoid-slug.png)](http://travis-ci.org/digitalplaywright/mongoid-slug) [![Dependency Status](https://gemnasium.com/digitalplaywright/mongoid-slug.png)](https://gemnasium.com/digitalplaywright/mongoid-slug) [![Code Climate](https://codeclimate.com/github/digitalplaywright/mongoid-slug.png)](https://codeclimate.com/github/digitalplaywright/mongoid-slug)
6
+ [![Build Status](https://secure.travis-ci.org/digitalplaywright/mongoid-slug.png)](http://travis-ci.org/digitalplaywright/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/digitalplaywright/mongoid-slug.png)](https://gemnasium.com/digitalplaywright/mongoid-slug)
9
+ [![Code Climate](https://codeclimate.com/github/digitalplaywright/mongoid-slug.png)](https://codeclimate.com/github/digitalplaywright/mongoid-slug)
12
10
 
13
11
  Installation
14
12
  ------------
@@ -72,7 +70,7 @@ post = Post.find 'a-thousand-plateaus' # Finds by slugs
72
70
  post = Post.find '50b1386a0482939864000001' # Finds by bson ids
73
71
  => ...
74
72
  ```
75
- [Read here] [4] for all available options.
73
+ [Examine slug.rb](lib/mongoid/slug.rb) for all available options.
76
74
 
77
75
  Custom Slug Generation
78
76
  -------
@@ -254,7 +252,7 @@ PS! A migration is needed to use Mongoid localized fields for documents that was
254
252
  feature was off. Anything else will cause errors.
255
253
 
256
254
  Custom Find Strategies
257
- --------------
255
+ ----------------------
258
256
 
259
257
  By default find will search for the document by the id field if the provided id
260
258
  looks like a BSON::ObjectId, and it will otherwise find by the _slugs field. However,
@@ -303,6 +301,7 @@ Mongoid::Paranoia Support
303
301
 
304
302
  The [Mongoid::Paranoia](http://github.com/simi/mongoid-paranoia) gem adds "soft-destroy" functionality to Mongoid documents.
305
303
  Mongoid::Slug contains special handling for Mongoid::Paranoia:
304
+
306
305
  - When destroying a paranoid document, the slug will be unset from the database.
307
306
  - When restoring a paranoid document, the slug will be rebuilt. Note that the new slug may not match the old one.
308
307
  - When resaving a destroyed paranoid document, the slug will remain unset in the database.
@@ -317,17 +316,18 @@ end
317
316
  ```
318
317
 
319
318
  The following variants of Mongoid Paranoia are officially supported:
319
+
320
320
  * Mongoid 3 built-in Mongoid::Paranoia
321
- * Mongoid 4 gem http://github.com/simi/mongoid-paranoia
321
+ * Mongoid 4 or 5 gem http://github.com/simi/mongoid_paranoia
322
+
323
+
324
+ Contributing
325
+ ------------
322
326
 
323
- Mongoid 4 gem "mongoid-paranoia" (http://github.com/haihappen/mongoid-paranoia)
324
- is not officially supported but should also work.
327
+ Mongoid-slug is work of [many of contributors](https://github.com/digitalplaywright/mongoid-slug/graphs/contributors). You're encouraged to submit [pull requests](https://github.com/digitalplaywright/mongoid-slug/pulls), [propose features, ask questions and discuss issues](https://github.com/digitalplaywright/mongoid-slug/issues). See [CONTRIBUTING](CONTRIBUTING.md) for details.
325
328
 
329
+ Copyright & License
330
+ -------------------
326
331
 
327
- References
328
- ----------
332
+ Copyright (c) 2010-2015 Hakan Ensari & Contributors, see [LICENSE](LICENSE) for details.
329
333
 
330
- [1]: https://github.com/rsl/stringex/
331
- [2]: https://secure.travis-ci.org/hakanensari/mongoid-slug.png
332
- [3]: http://travis-ci.org/hakanensari/mongoid-slug
333
- [4]: https://github.com/digitalplaywright/mongoid-slug/blob/master/lib/mongoid/slug.rb
@@ -5,6 +5,7 @@ require 'mongoid/slug/index'
5
5
  require 'mongoid/slug/paranoia'
6
6
  require 'mongoid/slug/unique_slug'
7
7
  require 'mongoid/slug/slug_id_strategy'
8
+ require 'mongoid-compatibility'
8
9
 
9
10
  module Mongoid
10
11
  # Slugs your Mongoid model.
@@ -59,8 +60,8 @@ module Mongoid
59
60
  options = fields.extract_options!
60
61
 
61
62
  self.slug_scope = options[:scope]
62
- self.reserved_words = options[:reserve] || Set.new(["new", "edit"])
63
- self.slugged_attributes = fields.map &:to_s
63
+ self.reserved_words = options[:reserve] || Set.new(%w(new edit))
64
+ self.slugged_attributes = fields.map(&:to_s)
64
65
  self.history = options[:history]
65
66
  self.by_model_type = options[:by_model_type]
66
67
 
@@ -69,7 +70,7 @@ module Mongoid
69
70
 
70
71
  # Set index
71
72
  unless embedded?
72
- index(*Mongoid::Slug::Index.build_index(self.slug_scope_key, self.by_model_type))
73
+ index(*Mongoid::Slug::Index.build_index(slug_scope_key, by_model_type))
73
74
  end
74
75
 
75
76
  #-- Why is it necessary to customize the slug builder?
@@ -84,7 +85,7 @@ module Mongoid
84
85
  if options[:permanent]
85
86
  set_callback :create, :before, :build_slug
86
87
  else
87
- set_callback :save, :before, :build_slug, :if => :slug_should_be_rebuilt?
88
+ set_callback :save, :before, :build_slug, if: :slug_should_be_rebuilt?
88
89
  end
89
90
 
90
91
  # If paranoid document:
@@ -93,11 +94,11 @@ module Mongoid
93
94
  # - recreate the slug on restore
94
95
  # - force reset the slug when saving a destroyed paranoid document, to ensure it stays unset in the database
95
96
  if is_paranoid_doc?
96
- self.send(:include, Mongoid::Slug::Paranoia) unless self.respond_to?(:before_restore)
97
+ send(:include, Mongoid::Slug::Paranoia) unless self.respond_to?(:before_restore)
97
98
  set_callback :destroy, :after, :unset_slug!
98
99
  set_callback :restore, :before, :set_slug!
99
- set_callback :save, :before, :reset_slug!, :if => :paranoid_deleted?
100
- set_callback :save, :after, :clear_slug!, :if => :paranoid_deleted?
100
+ set_callback :save, :before, :reset_slug!, if: :paranoid_deleted?
101
+ set_callback :save, :after, :clear_slug!, if: :paranoid_deleted?
101
102
  end
102
103
  end
103
104
 
@@ -109,8 +110,8 @@ module Mongoid
109
110
  #
110
111
  # @return [ Array<Document>, Document ] Whether the document is paranoid
111
112
  def slug_scope_key
112
- return nil unless self.slug_scope
113
- self.reflect_on_association(self.slug_scope).try(:key) || self.slug_scope
113
+ return nil unless slug_scope
114
+ reflect_on_association(slug_scope).try(:key) || slug_scope
114
115
  end
115
116
 
116
117
  # Find documents by slugs.
@@ -135,7 +136,8 @@ module Mongoid
135
136
  end
136
137
 
137
138
  def queryable
138
- scope_stack.last || Criteria.new(self) # Use Mongoid::Slug::Criteria for slugged documents.
139
+ scope = Mongoid::Compatibility::Version.mongoid5? ? Threaded.current_scope : scope_stack.last
140
+ scope || Criteria.new(self) # Use Mongoid::Slug::Criteria for slugged documents.
139
141
  end
140
142
 
141
143
  # Indicates whether or not the document includes Mongoid::Paranoia
@@ -171,19 +173,19 @@ module Mongoid
171
173
  end
172
174
 
173
175
  def apply_slug
174
- _new_slug = find_unique_slug
176
+ new_slug = find_unique_slug
175
177
 
176
- #skip slug generation and use Mongoid id
177
- #to find document instead
178
- return true if _new_slug.size == 0
178
+ # skip slug generation and use Mongoid id
179
+ # to find document instead
180
+ return true if new_slug.size == 0
179
181
 
180
182
  # avoid duplicate slugs
181
- self._slugs.delete(_new_slug) if self._slugs
183
+ _slugs.delete(new_slug) if _slugs
182
184
 
183
- if !!self.history && self._slugs.is_a?(Array)
184
- append_slug(_new_slug)
185
+ if !!history && _slugs.is_a?(Array)
186
+ append_slug(new_slug)
185
187
  else
186
- self._slugs = [_new_slug]
188
+ self._slugs = [new_slug]
187
189
  end
188
190
  end
189
191
 
@@ -194,7 +196,7 @@ module Mongoid
194
196
  # Mongoid 3 (two args) and Mongoid 4 (hash arg)
195
197
  def set_slug!
196
198
  build_slug
197
- self.method(:set).arity == 1 ? set({_slugs: self._slugs}) : set(:_slugs, self._slugs)
199
+ method(:set).arity == 1 ? set(_slugs: _slugs) : set(:_slugs, _slugs)
198
200
  end
199
201
 
200
202
  # Atomically unsets the slug field in the database. It is important to unset
@@ -228,7 +230,7 @@ module Mongoid
228
230
 
229
231
  # @return [Boolean] Whether the slug requires to be rebuilt
230
232
  def slug_should_be_rebuilt?
231
- (new_record? or _slugs_changed? or slugged_attributes_changed?) and !paranoid_deleted?
233
+ (new_record? || _slugs_changed? || slugged_attributes_changed?) && !paranoid_deleted?
232
234
  end
233
235
 
234
236
  # Indicates whether or not the document has been deleted in paranoid fashion
@@ -236,7 +238,7 @@ module Mongoid
236
238
  #
237
239
  # @return [Boolean] Whether or not the document has been deleted in paranoid fashion
238
240
  def paranoid_deleted?
239
- !!(self.class.is_paranoid_doc? and self.deleted_at != nil)
241
+ !!(self.class.is_paranoid_doc? && !deleted_at.nil?)
240
242
  end
241
243
 
242
244
  def slugged_attributes_changed?
@@ -252,17 +254,17 @@ module Mongoid
252
254
  # @return [String] the slug, or nil if the document does not have a slug.
253
255
  def slug
254
256
  return _slugs.last if _slugs
255
- return _id.to_s
257
+ _id.to_s
256
258
  end
257
259
 
258
260
  def slug_builder
259
- _cur_slug = nil
260
- if new_with_slugs? or persisted_with_slug_changes?
261
- #user defined slug
262
- _cur_slug = _slugs.last
261
+ cur_slug = nil
262
+ if new_with_slugs? || persisted_with_slug_changes?
263
+ # user defined slug
264
+ cur_slug = _slugs.last
263
265
  end
264
- #generate slug if the slug is not user defined or does not exist
265
- _cur_slug || pre_slug_string
266
+ # generate slug if the slug is not user defined or does not exist
267
+ cur_slug || pre_slug_string
266
268
  end
267
269
 
268
270
  def self.mongoid3?
@@ -271,16 +273,16 @@ module Mongoid
271
273
 
272
274
  private
273
275
 
274
- def append_slug(_slug)
276
+ def append_slug(value)
275
277
  if localized?
276
278
  # This is necessary for the scenario in which the slugged locale is not yet present
277
279
  # but the default locale is. In this situation, self._slugs falls back to the default
278
280
  # which is undesired
279
- current_slugs = self._slugs_translations.fetch(I18n.locale.to_s, [])
280
- current_slugs << _slug
281
- self._slugs_translations = self._slugs_translations.merge(I18n.locale.to_s => current_slugs)
281
+ current_slugs = _slugs_translations.fetch(I18n.locale.to_s, [])
282
+ current_slugs << value
283
+ self._slugs_translations = _slugs_translations.merge(I18n.locale.to_s => current_slugs)
282
284
  else
283
- self._slugs << _slug
285
+ _slugs << value
284
286
  end
285
287
  end
286
288
 
@@ -289,29 +291,31 @@ module Mongoid
289
291
  if localized?
290
292
  # We need to check if slugs are present for the locale without falling back
291
293
  # to a default
292
- new_record? and _slugs_translations.fetch(I18n.locale.to_s, []).any?
294
+ new_record? && _slugs_translations.fetch(I18n.locale.to_s, []).any?
293
295
  else
294
- new_record? and _slugs.present?
296
+ new_record? && _slugs.present?
295
297
  end
296
298
  end
297
299
 
298
300
  # Returns true if object has been persisted and has changes in the slug
299
301
  def persisted_with_slug_changes?
300
302
  if localized?
301
- changes = self._slugs_change
302
- return (persisted? and false) if changes.nil?
303
+ changes = _slugs_change
304
+ return (persisted? && false) if changes.nil?
303
305
 
304
306
  # ensure we check for changes only between the same locale
305
307
  original = changes.first.try(:fetch, I18n.locale.to_s, nil)
306
308
  compare = changes.last.try(:fetch, I18n.locale.to_s, nil)
307
- persisted? and original != compare
309
+ persisted? && original != compare
308
310
  else
309
- persisted? and _slugs_changed?
311
+ persisted? && _slugs_changed?
310
312
  end
311
313
  end
312
314
 
313
315
  def localized?
314
- self.fields['_slugs'].options[:localize] rescue false
316
+ fields['_slugs'].options[:localize]
317
+ rescue
318
+ false
315
319
  end
316
320
 
317
321
  # Return all possible locales for model
@@ -319,15 +323,15 @@ module Mongoid
319
323
  # doing something crazy, but at the same time we need a fallback in case the model doesn't
320
324
  # have any localized attributes at all (extreme edge case).
321
325
  def all_locales
322
- locales = self.slugged_attributes
323
- .map{|attr| self.send("#{attr}_translations").keys if self.respond_to?("#{attr}_translations")}
324
- .flatten.compact.uniq
326
+ locales = slugged_attributes
327
+ .map { |attr| send("#{attr}_translations").keys if self.respond_to?("#{attr}_translations") }
328
+ .flatten.compact.uniq
325
329
  locales = I18n.available_locales if locales.empty?
326
330
  locales
327
331
  end
328
332
 
329
333
  def pre_slug_string
330
- self.slugged_attributes.map { |f| self.send f }.join ' '
334
+ slugged_attributes.map { |f| send f }.join ' '
331
335
  end
332
336
  end
333
337
  end
@@ -60,13 +60,13 @@ module Mongoid
60
60
  # unless a :slug_id_strategy option is defined on the id field,
61
61
  # use object_id or string strategy depending on the id_type
62
62
  # otherwise default for all other id_types
63
- def build_slug_strategy id_type
64
- type_method = id_type.to_s.downcase.split('::').last + "_slug_strategy"
65
- self.respond_to?(type_method, true) ? method(type_method) : lambda {|id| false}
63
+ def build_slug_strategy(id_type)
64
+ type_method = id_type.to_s.downcase.split('::').last + '_slug_strategy'
65
+ self.respond_to?(type_method, true) ? method(type_method) : ->(_id) { false }
66
66
  end
67
67
 
68
68
  # a string will not look like a slug if it looks like a legal BSON::ObjectId
69
- def objectid_slug_strategy id
69
+ def objectid_slug_strategy(id)
70
70
  if Mongoid::Slug.mongoid3?
71
71
  Moped::BSON::ObjectId.legal? id
72
72
  else
@@ -75,20 +75,23 @@ module Mongoid
75
75
  end
76
76
 
77
77
  # a string will always look like a slug
78
- def string_slug_strategy id
78
+ def string_slug_strategy(_id)
79
79
  true
80
80
  end
81
81
 
82
-
83
82
  def for_slugs(slugs)
84
- #_translations
85
- localized = (@klass.fields['_slugs'].options[:localize] rescue false)
83
+ # _translations
84
+ localized = (begin
85
+ @klass.fields['_slugs'].options[:localize]
86
+ rescue
87
+ false
88
+ end)
86
89
  if localized
87
90
  def_loc = I18n.default_locale
88
91
  query = { '$in' => slugs }
89
- where({'$or' => [{ _slugs: query }, { "_slugs.#{def_loc}" => query }]}).limit(slugs.length)
92
+ where({ '$or' => [{ _slugs: query }, { "_slugs.#{def_loc}" => query }] }).limit(slugs.length)
90
93
  else
91
- where({ _slugs: { '$in' => slugs } }).limit(slugs.length)
94
+ where(_slugs: { '$in' => slugs }).limit(slugs.length)
92
95
  end
93
96
  end
94
97
 
@@ -102,7 +105,7 @@ module Mongoid
102
105
  missing_slugs = slugs - result.map(&:slugs).flatten
103
106
 
104
107
  if !missing_slugs.blank? && Mongoid.raise_not_found_error
105
- raise Errors::DocumentNotFound.new(klass, slugs, missing_slugs)
108
+ fail Errors::DocumentNotFound.new(klass, slugs, missing_slugs)
106
109
  end
107
110
  end
108
111
  end
@@ -1,26 +1,23 @@
1
1
  module Mongoid
2
2
  module Slug
3
3
  module Index
4
-
5
4
  # @param [ String or Symbol ] scope_key The optional scope key for the index
6
5
  # @param [ Boolean ] by_model_type Whether or not
7
6
  #
8
7
  # @return [ Array(Hash, Hash) ] the indexable fields and index options.
9
8
  def self.build_index(scope_key = nil, by_model_type = false)
10
- fields = {_slugs: 1}
9
+ fields = { _slugs: 1 }
11
10
  options = {}
12
11
 
13
- if scope_key
14
- fields.merge!({scope_key => 1})
15
- end
12
+ fields.merge!(scope_key => 1) if scope_key
16
13
 
17
14
  if by_model_type
18
- fields.merge!({_type: 1})
15
+ fields.merge!(_type: 1)
19
16
  else
20
- options.merge!({unique: true, sparse: true})
17
+ options.merge!(unique: true, sparse: true)
21
18
  end
22
19
 
23
- return [fields, options]
20
+ [fields, options]
24
21
  end
25
22
  end
26
23
  end
@@ -1,13 +1,11 @@
1
1
  module Mongoid
2
2
  module Slug
3
-
4
3
  # Lightweight compatibility shim which adds the :restore callback to
5
4
  # older versions of Mongoid::Paranoia
6
5
  module Paranoia
7
6
  extend ActiveSupport::Concern
8
7
 
9
8
  included do
10
-
11
9
  define_model_callbacks :restore
12
10
 
13
11
  def restore_with_callbacks
@@ -1,3 +1,3 @@
1
- Mongoid::Fields.option(:slug_id_strategy) do |model, field, value|
1
+ Mongoid::Fields.option(:slug_id_strategy) do |_model, field, value|
2
2
  field.options[:slug_id_strategy] = value
3
3
  end
@@ -8,7 +8,7 @@ module Mongoid
8
8
  class SlugState
9
9
  attr_reader :last_entered_slug, :existing_slugs, :existing_history_slugs, :sorted_existing
10
10
 
11
- def initialize slug, documents, pattern
11
+ def initialize(slug, documents, pattern)
12
12
  @slug = slug
13
13
  @documents = documents
14
14
  @pattern = pattern
@@ -21,7 +21,7 @@ module Mongoid
21
21
  next if history_slugs.nil?
22
22
  existing_slugs.push(*history_slugs.find_all { |cur_slug| cur_slug =~ @pattern })
23
23
  last_entered_slug.push(*history_slugs.last) if history_slugs.last =~ @pattern
24
- existing_history_slugs.push(*history_slugs.first(history_slugs.length() - 1).find_all { |cur_slug| cur_slug =~ @pattern })
24
+ existing_history_slugs.push(*history_slugs.first(history_slugs.length - 1).find_all { |cur_slug| cur_slug =~ @pattern })
25
25
  end
26
26
  end
27
27
 
@@ -40,19 +40,19 @@ module Mongoid
40
40
 
41
41
  def sort_existing_slugs
42
42
  # remove the slug part and leave the absolute integer part and sort
43
- re = %r(^#{Regexp.escape(@slug)})
43
+ re = /^#{Regexp.escape(@slug)}/
44
44
  @sorted_existing = existing_slugs.map do |s|
45
- s.sub(re,'').to_i.abs
45
+ s.sub(re, '').to_i.abs
46
46
  end.sort
47
47
  end
48
48
 
49
49
  def inspect
50
50
  {
51
- :slug => @slug,
52
- :existing_slugs => existing_slugs,
53
- :last_entered_slug => last_entered_slug,
54
- :existing_history_slugs => existing_history_slugs,
55
- :sorted_existing => sorted_existing
51
+ slug: @slug,
52
+ existing_slugs: existing_slugs,
53
+ last_entered_slug: last_entered_slug,
54
+ existing_history_slugs: existing_history_slugs,
55
+ sorted_existing: sorted_existing
56
56
  }
57
57
  end
58
58
  end
@@ -62,12 +62,12 @@ module Mongoid
62
62
  attr_reader :model, :_slug
63
63
 
64
64
  def_delegators :@model, :slug_scope, :reflect_on_association, :read_attribute,
65
- :check_against_id, :reserved_words, :url_builder, :collection_name,
66
- :embedded?, :reflect_on_all_associations, :by_model_type
65
+ :check_against_id, :reserved_words, :url_builder, :collection_name,
66
+ :embedded?, :reflect_on_all_associations, :by_model_type
67
67
 
68
- def initialize model
68
+ def initialize(model)
69
69
  @model = model
70
- @_slug = ""
70
+ @_slug = ''
71
71
  @state = nil
72
72
  end
73
73
 
@@ -75,40 +75,40 @@ module Mongoid
75
75
  @model.respond_to?(:relation_metadata) ? @model.relation_metadata : @model.metadata
76
76
  end
77
77
 
78
- def find_unique attempt = nil
78
+ def find_unique(attempt = nil)
79
79
  MUTEX_FOR_SLUG.synchronize do
80
80
  @_slug = if attempt
81
- attempt.to_url
82
- else
83
- url_builder.call(model)
84
- end
81
+ attempt.to_url
82
+ else
83
+ url_builder.call(model)
84
+ end
85
85
  # Regular expression that matches slug, slug-1, ... slug-n
86
86
  # If slug_name field was indexed, MongoDB will utilize that
87
87
  # index to match /^.../ pattern.
88
88
  pattern = /^#{Regexp.escape(@_slug)}(?:-(\d+))?$/
89
-
89
+
90
90
  where_hash = {}
91
91
  where_hash[:_slugs.all] = [pattern]
92
92
  where_hash[:_id.ne] = model._id
93
-
93
+
94
94
  if (scope = slug_scope) && reflect_on_association(scope).nil?
95
95
  # scope is not an association, so it's scoped to a local field
96
96
  # (e.g. an association id in a denormalized db design)
97
97
  where_hash[scope] = model.try(:read_attribute, scope)
98
98
  end
99
-
99
+
100
100
  if by_model_type == true
101
101
  where_hash[:_type] = model.try(:read_attribute, :_type)
102
102
  end
103
-
103
+
104
104
  @state = SlugState.new @_slug, uniqueness_scope.unscoped.where(where_hash), pattern
105
-
105
+
106
106
  # do not allow a slug that can be interpreted as the current document id
107
107
  @state.include_slug unless model.class.look_like_slugs?([@_slug])
108
-
108
+
109
109
  # make sure that the slug is not equal to a reserved word
110
110
  @state.include_slug if reserved_words.any? { |word| word === @_slug }
111
-
111
+
112
112
  # only look for a new unique slug if the existing slugs contains the current slug
113
113
  # - e.g if the slug 'foo-2' is taken, but 'foo' is available, the user can use 'foo'.
114
114
  if @state.slug_included?
@@ -120,9 +120,7 @@ module Mongoid
120
120
  end
121
121
 
122
122
  def uniqueness_scope
123
-
124
- if slug_scope &&
125
- metadata = reflect_on_association(slug_scope)
123
+ if slug_scope && (metadata = reflect_on_association(slug_scope))
126
124
 
127
125
  parent = model.send(metadata.name)
128
126
 
@@ -141,7 +139,7 @@ module Mongoid
141
139
  return model._parent.send(parent_metadata.inverse_of || self.metadata.name)
142
140
  end
143
141
 
144
- #unless embedded or slug scope, return the deepest document superclass
142
+ # unless embedded or slug scope, return the deepest document superclass
145
143
  appropriate_class = model.class
146
144
  while appropriate_class.superclass.include?(Mongoid::Document)
147
145
  appropriate_class = appropriate_class.superclass