mongoid_slug 3.2.1 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +31 -1
- data/lib/mongoid/slug.rb +82 -22
- data/lib/mongoid/slug/index.rb +27 -0
- data/lib/mongoid/slug/paranoia.rb +22 -0
- data/lib/mongoid/slug/unique_slug.rb +41 -39
- data/lib/mongoid/slug/version.rb +1 -1
- data/lib/mongoid_slug.rb +1 -5
- data/spec/models/page.rb +1 -1
- data/spec/models/page_localize.rb +1 -1
- data/spec/models/page_slug_localized.rb +1 -1
- data/spec/models/page_slug_localized_history.rb +1 -1
- data/spec/models/paranoid_permanent.rb +8 -0
- data/spec/mongoid/index_spec.rb +34 -0
- data/spec/mongoid/paranoia_spec.rb +169 -0
- data/spec/mongoid/slug_spec.rb +4 -24
- data/spec/spec_helper.rb +10 -4
- metadata +30 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d7c5482b8203ac1d0077abb6d57c9b2395a8833c
|
4
|
+
data.tar.gz: 46495e284ce06a65efac3ff1105a8cc5f07042f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dbb1ca989496522277f6c1b684df643a621e993b1a9f227de32331c5de15d65dcbfdc049588aadb2fbe1b3cb232f827012265cf4c336e53a128a965b6cf264f8
|
7
|
+
data.tar.gz: e8a8e0a3fce03e2505ee2f9e82d9dea61ddccfa23ffc02195ef2a67d8a8504524a54fd829fbf804e7879606e5ae610e95b1cb68e12190bc3a1a5e40f0222c4c3
|
data/README.md
CHANGED
@@ -16,7 +16,7 @@ Installation
|
|
16
16
|
Add to your Gemfile:
|
17
17
|
|
18
18
|
```ruby
|
19
|
-
gem '
|
19
|
+
gem 'mongoid-slug'
|
20
20
|
```
|
21
21
|
|
22
22
|
Usage
|
@@ -297,6 +297,36 @@ unique = Mongoid::Slug::UniqueSlug.new(Book.new).find_unique(title)
|
|
297
297
|
# return some representation of unique
|
298
298
|
```
|
299
299
|
|
300
|
+
|
301
|
+
Mongoid::Paranoia Support
|
302
|
+
-------------------------
|
303
|
+
|
304
|
+
The [Mongoid::Paranoia](http://github.com/simi/mongoid-paranoia) gem adds "soft-destroy" functionality to Mongoid documents.
|
305
|
+
Mongoid::Slug contains special handling for Mongoid::Paranoia:
|
306
|
+
- When destroying a paranoid document, the slug will be unset from the database.
|
307
|
+
- When restoring a paranoid document, the slug will be rebuilt. Note that the new slug may not match the old one.
|
308
|
+
- When resaving a destroyed paranoid document, the slug will remain unset in the database.
|
309
|
+
- For indexing purposes, sparse unique indexes are used. The sparse condition will ignore any destroyed paranoid documents, since their slug is not set in database.
|
310
|
+
|
311
|
+
```ruby
|
312
|
+
class Entity
|
313
|
+
include Mongoid::Document
|
314
|
+
include Mongoid::Slug
|
315
|
+
include Mongoid::Paranoia
|
316
|
+
end
|
317
|
+
```
|
318
|
+
|
319
|
+
The following variants of Mongoid Paranoia are officially supported:
|
320
|
+
* Mongoid 3 built-in Mongoid::Paranoia
|
321
|
+
* Mongoid 4 gem http://github.com/simi/mongoid-paranoia
|
322
|
+
|
323
|
+
Mongoid 4 gem "mongoid-paranoia" (http://github.com/haihappen/mongoid-paranoia)
|
324
|
+
is not officially supported but should also work.
|
325
|
+
|
326
|
+
|
327
|
+
References
|
328
|
+
----------
|
329
|
+
|
300
330
|
[1]: https://github.com/rsl/stringex/
|
301
331
|
[2]: https://secure.travis-ci.org/hakanensari/mongoid-slug.png
|
302
332
|
[3]: http://travis-ci.org/hakanensari/mongoid-slug
|
data/lib/mongoid/slug.rb
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
require 'mongoid'
|
2
|
+
require 'stringex'
|
3
|
+
require 'mongoid/slug/criteria'
|
4
|
+
require 'mongoid/slug/index'
|
5
|
+
require 'mongoid/slug/paranoia'
|
6
|
+
require 'mongoid/slug/unique_slug'
|
7
|
+
require 'mongoid/slug/slug_id_strategy'
|
8
|
+
|
1
9
|
module Mongoid
|
2
10
|
# Slugs your Mongoid model.
|
3
11
|
module Slug
|
@@ -59,24 +67,9 @@ module Mongoid
|
|
59
67
|
field :_slugs, type: Array, default: [], localize: options[:localize]
|
60
68
|
alias_attribute :slugs, :_slugs
|
61
69
|
|
70
|
+
# Set index
|
62
71
|
unless embedded?
|
63
|
-
|
64
|
-
scope_key = (metadata = self.reflect_on_association(slug_scope)) ? metadata.key : slug_scope
|
65
|
-
if options[:by_model_type] == true
|
66
|
-
# Add _type to the index to fix polymorphism
|
67
|
-
index({ _type: 1, scope_key => 1, _slugs: 1})
|
68
|
-
else
|
69
|
-
index({scope_key => 1, _slugs: 1}, {unique: true, sparse: true})
|
70
|
-
end
|
71
|
-
|
72
|
-
else
|
73
|
-
# Add _type to the index to fix polymorphism
|
74
|
-
if options[:by_model_type] == true
|
75
|
-
index({_type: 1, _slugs: 1})
|
76
|
-
else
|
77
|
-
index({_slugs: 1}, {unique: true, sparse: true})
|
78
|
-
end
|
79
|
-
end
|
72
|
+
index(*Mongoid::Slug::Index.build_index(self.slug_scope_key, self.by_model_type))
|
80
73
|
end
|
81
74
|
|
82
75
|
#-- Why is it necessary to customize the slug builder?
|
@@ -93,12 +86,33 @@ module Mongoid
|
|
93
86
|
else
|
94
87
|
set_callback :save, :before, :build_slug, :if => :slug_should_be_rebuilt?
|
95
88
|
end
|
89
|
+
|
90
|
+
# If paranoid document:
|
91
|
+
# - include shim to add callbacks for restore method
|
92
|
+
# - unset the slugs on destroy
|
93
|
+
# - recreate the slug on restore
|
94
|
+
# - force reset the slug when saving a destroyed paranoid document, to ensure it stays unset in the database
|
95
|
+
if is_paranoid_doc?
|
96
|
+
self.send(:include, Mongoid::Slug::Paranoia) unless self.respond_to?(:before_restore)
|
97
|
+
set_callback :destroy, :after, :unset_slug!
|
98
|
+
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?
|
101
|
+
end
|
96
102
|
end
|
97
103
|
|
98
104
|
def look_like_slugs?(*args)
|
99
105
|
with_default_scope.look_like_slugs?(*args)
|
100
106
|
end
|
101
107
|
|
108
|
+
# Returns the scope key for indexing, considering associations
|
109
|
+
#
|
110
|
+
# @return [ Array<Document>, Document ] Whether the document is paranoid
|
111
|
+
def slug_scope_key
|
112
|
+
return nil unless self.slug_scope
|
113
|
+
self.reflect_on_association(self.slug_scope).try(:key) || self.slug_scope
|
114
|
+
end
|
115
|
+
|
102
116
|
# Find documents by slugs.
|
103
117
|
#
|
104
118
|
# A document matches if any of its slugs match one of the supplied params.
|
@@ -124,6 +138,16 @@ module Mongoid
|
|
124
138
|
scope_stack.last || Criteria.new(self) # Use Mongoid::Slug::Criteria for slugged documents.
|
125
139
|
end
|
126
140
|
|
141
|
+
# Indicates whether or not the document includes Mongoid::Paranoia
|
142
|
+
#
|
143
|
+
# This can be replaced with .paranoid? method once the following PRs are merged:
|
144
|
+
# - https://github.com/simi/mongoid-paranoia/pull/19
|
145
|
+
# - https://github.com/haihappen/mongoid-paranoia/pull/3
|
146
|
+
#
|
147
|
+
# @return [ Array<Document>, Document ] Whether the document is paranoid
|
148
|
+
def is_paranoid_doc?
|
149
|
+
!!(defined?(::Mongoid::Paranoia) && self < ::Mongoid::Paranoia)
|
150
|
+
end
|
127
151
|
end
|
128
152
|
|
129
153
|
# Builds a new slug.
|
@@ -135,18 +159,18 @@ module Mongoid
|
|
135
159
|
orig_locale = I18n.locale
|
136
160
|
all_locales.each do |target_locale|
|
137
161
|
I18n.locale = target_locale
|
138
|
-
|
162
|
+
apply_slug
|
139
163
|
end
|
140
164
|
ensure
|
141
165
|
I18n.locale = orig_locale
|
142
166
|
end
|
143
167
|
else
|
144
|
-
|
168
|
+
apply_slug
|
145
169
|
end
|
146
170
|
true
|
147
171
|
end
|
148
172
|
|
149
|
-
def
|
173
|
+
def apply_slug
|
150
174
|
_new_slug = find_unique_slug
|
151
175
|
|
152
176
|
#skip slug generation and use Mongoid id
|
@@ -163,6 +187,35 @@ module Mongoid
|
|
163
187
|
end
|
164
188
|
end
|
165
189
|
|
190
|
+
# Builds slug then atomically sets it in the database.
|
191
|
+
# This is used when working with the Mongoid::Paranoia restore callback.
|
192
|
+
#
|
193
|
+
# This method is adapted to use the :set method variants from both
|
194
|
+
# Mongoid 3 (two args) and Mongoid 4 (hash arg)
|
195
|
+
def set_slug!
|
196
|
+
build_slug
|
197
|
+
self.method(:set).arity == 1 ? set({_slugs: self._slugs}) : set(:_slugs, self._slugs)
|
198
|
+
end
|
199
|
+
|
200
|
+
# Atomically unsets the slug field in the database. It is important to unset
|
201
|
+
# the field for the sparse index on slugs.
|
202
|
+
#
|
203
|
+
# This also resets the in-memory value of the slug field to its default (empty array)
|
204
|
+
def unset_slug!
|
205
|
+
unset(:_slugs)
|
206
|
+
clear_slug!
|
207
|
+
end
|
208
|
+
|
209
|
+
# Rolls back the slug value from the Mongoid changeset.
|
210
|
+
def reset_slug!
|
211
|
+
self.reset__slugs!
|
212
|
+
end
|
213
|
+
|
214
|
+
# Sets the slug to its default value.
|
215
|
+
def clear_slug!
|
216
|
+
self._slugs = []
|
217
|
+
end
|
218
|
+
|
166
219
|
# Finds a unique slug, were specified string used to generate a slug.
|
167
220
|
#
|
168
221
|
# Returned slug will the same as the specified string when there are no
|
@@ -175,7 +228,15 @@ module Mongoid
|
|
175
228
|
|
176
229
|
# @return [Boolean] Whether the slug requires to be rebuilt
|
177
230
|
def slug_should_be_rebuilt?
|
178
|
-
new_record? or _slugs_changed? or slugged_attributes_changed?
|
231
|
+
(new_record? or _slugs_changed? or slugged_attributes_changed?) and !paranoid_deleted?
|
232
|
+
end
|
233
|
+
|
234
|
+
# Indicates whether or not the document has been deleted in paranoid fashion
|
235
|
+
# Always returns false if the document is not paranoid
|
236
|
+
#
|
237
|
+
# @return [Boolean] Whether or not the document has been deleted in paranoid fashion
|
238
|
+
def paranoid_deleted?
|
239
|
+
!!(self.class.is_paranoid_doc? and self.deleted_at != nil)
|
179
240
|
end
|
180
241
|
|
181
242
|
def slugged_attributes_changed?
|
@@ -270,4 +331,3 @@ module Mongoid
|
|
270
331
|
end
|
271
332
|
end
|
272
333
|
end
|
273
|
-
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Slug
|
3
|
+
module Index
|
4
|
+
|
5
|
+
# @param [ String or Symbol ] scope_key The optional scope key for the index
|
6
|
+
# @param [ Boolean ] by_model_type Whether or not
|
7
|
+
#
|
8
|
+
# @return [ Array(Hash, Hash) ] the indexable fields and index options.
|
9
|
+
def self.build_index(scope_key = nil, by_model_type = false)
|
10
|
+
fields = {_slugs: 1}
|
11
|
+
options = {}
|
12
|
+
|
13
|
+
if scope_key
|
14
|
+
fields.merge!({scope_key => 1})
|
15
|
+
end
|
16
|
+
|
17
|
+
if by_model_type
|
18
|
+
fields.merge!({_type: 1})
|
19
|
+
else
|
20
|
+
options.merge!({unique: true, sparse: true})
|
21
|
+
end
|
22
|
+
|
23
|
+
return [fields, options]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Slug
|
3
|
+
|
4
|
+
# Lightweight compatibility shim which adds the :restore callback to
|
5
|
+
# older versions of Mongoid::Paranoia
|
6
|
+
module Paranoia
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
|
11
|
+
define_model_callbacks :restore
|
12
|
+
|
13
|
+
def restore_with_callbacks
|
14
|
+
run_callbacks(:restore) do
|
15
|
+
restore_without_callbacks
|
16
|
+
end
|
17
|
+
end
|
18
|
+
alias_method_chain :restore, :callbacks
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -4,7 +4,7 @@ require 'forwardable'
|
|
4
4
|
module Mongoid
|
5
5
|
module Slug
|
6
6
|
class UniqueSlug
|
7
|
-
|
7
|
+
MUTEX_FOR_SLUG = Mutex.new
|
8
8
|
class SlugState
|
9
9
|
attr_reader :last_entered_slug, :existing_slugs, :existing_history_slugs, :sorted_existing
|
10
10
|
|
@@ -76,45 +76,47 @@ module Mongoid
|
|
76
76
|
end
|
77
77
|
|
78
78
|
def find_unique attempt = nil
|
79
|
-
|
80
|
-
attempt
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
79
|
+
MUTEX_FOR_SLUG.synchronize do
|
80
|
+
@_slug = if attempt
|
81
|
+
attempt.to_url
|
82
|
+
else
|
83
|
+
url_builder.call(model)
|
84
|
+
end
|
85
|
+
# Regular expression that matches slug, slug-1, ... slug-n
|
86
|
+
# If slug_name field was indexed, MongoDB will utilize that
|
87
|
+
# index to match /^.../ pattern.
|
88
|
+
pattern = /^#{Regexp.escape(@_slug)}(?:-(\d+))?$/
|
89
|
+
|
90
|
+
where_hash = {}
|
91
|
+
where_hash[:_slugs.all] = [pattern]
|
92
|
+
where_hash[:_id.ne] = model._id
|
93
|
+
|
94
|
+
if (scope = slug_scope) && reflect_on_association(scope).nil?
|
95
|
+
# scope is not an association, so it's scoped to a local field
|
96
|
+
# (e.g. an association id in a denormalized db design)
|
97
|
+
where_hash[scope] = model.try(:read_attribute, scope)
|
98
|
+
end
|
99
|
+
|
100
|
+
if by_model_type == true
|
101
|
+
where_hash[:_type] = model.try(:read_attribute, :_type)
|
102
|
+
end
|
103
|
+
|
104
|
+
@state = SlugState.new @_slug, uniqueness_scope.unscoped.where(where_hash), pattern
|
105
|
+
|
106
|
+
# do not allow a slug that can be interpreted as the current document id
|
107
|
+
@state.include_slug unless model.class.look_like_slugs?([@_slug])
|
108
|
+
|
109
|
+
# make sure that the slug is not equal to a reserved word
|
110
|
+
@state.include_slug if reserved_words.any? { |word| word === @_slug }
|
111
|
+
|
112
|
+
# only look for a new unique slug if the existing slugs contains the current slug
|
113
|
+
# - e.g if the slug 'foo-2' is taken, but 'foo' is available, the user can use 'foo'.
|
114
|
+
if @state.slug_included?
|
115
|
+
highest = @state.highest_existing_counter
|
116
|
+
@_slug += "-#{highest.succ}"
|
117
|
+
end
|
118
|
+
@_slug
|
116
119
|
end
|
117
|
-
@_slug
|
118
120
|
end
|
119
121
|
|
120
122
|
def uniqueness_scope
|
data/lib/mongoid/slug/version.rb
CHANGED
data/lib/mongoid_slug.rb
CHANGED
data/spec/models/page.rb
CHANGED
@@ -0,0 +1,34 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
describe Mongoid::Slug::Index do
|
5
|
+
|
6
|
+
let(:scope_key) { nil }
|
7
|
+
let(:by_model_type) { false }
|
8
|
+
subject { Mongoid::Slug::Index.build_index(scope_key, by_model_type) }
|
9
|
+
|
10
|
+
context "when scope_key is set" do
|
11
|
+
let(:scope_key) { :foo }
|
12
|
+
|
13
|
+
context "when by_model_type is true" do
|
14
|
+
let(:by_model_type) { true }
|
15
|
+
it { should eq [{:_slugs=>1, :foo=>1, :_type=>1}, {}] }
|
16
|
+
end
|
17
|
+
|
18
|
+
context "when by_model_type is false" do
|
19
|
+
it { should eq [{:_slugs=>1, :foo=>1}, {:unique=>true, :sparse=>true}] }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "when scope_key is not set" do
|
24
|
+
|
25
|
+
context "when by_model_type is true" do
|
26
|
+
let(:by_model_type) { true }
|
27
|
+
it { should eq [{:_slugs=>1, :_type=>1}, {}] }
|
28
|
+
end
|
29
|
+
|
30
|
+
context "when by_model_type is false" do
|
31
|
+
it { should eq [{:_slugs=>1}, {:unique=>true, :sparse=>true}] }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
describe "Mongoid::Paranoia with Mongoid::Slug" do
|
5
|
+
|
6
|
+
let(:paranoid_doc) { ParanoidDocument.create!(:title => "slug") }
|
7
|
+
let(:paranoid_doc_2) { ParanoidDocument.create!(:title => "slug") }
|
8
|
+
let(:paranoid_perm) { ParanoidPermanent.create!(:title => "slug") }
|
9
|
+
let(:paranoid_perm_2) { ParanoidPermanent.create!(:title => "slug") }
|
10
|
+
let(:non_paranoid_doc){ Article.create!(:title => "slug") }
|
11
|
+
subject{ paranoid_doc }
|
12
|
+
|
13
|
+
describe ".paranoid?" do
|
14
|
+
|
15
|
+
context "when Mongoid::Paranoia is included" do
|
16
|
+
subject { paranoid_doc.class }
|
17
|
+
its(:is_paranoid_doc?){ should be_truthy }
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when Mongoid::Paranoia not included" do
|
21
|
+
subject { non_paranoid_doc.class }
|
22
|
+
its(:is_paranoid_doc?){ should be_falsey }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#paranoid_deleted?" do
|
27
|
+
|
28
|
+
context "when Mongoid::Paranoia is included" do
|
29
|
+
|
30
|
+
context "when not destroyed" do
|
31
|
+
its(:paranoid_deleted?){ should be_falsey }
|
32
|
+
end
|
33
|
+
|
34
|
+
context "when destroyed" do
|
35
|
+
before { subject.destroy }
|
36
|
+
its(:paranoid_deleted?){ should be_truthy }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "when Mongoid::Paranoia not included" do
|
41
|
+
subject { non_paranoid_doc }
|
42
|
+
its(:paranoid_deleted?){ should be_falsey }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "restore callbacks" do
|
47
|
+
|
48
|
+
context "when Mongoid::Paranoia is included" do
|
49
|
+
subject { paranoid_doc.class }
|
50
|
+
it { should respond_to(:before_restore) }
|
51
|
+
it { should respond_to(:after_restore) }
|
52
|
+
end
|
53
|
+
|
54
|
+
context "when Mongoid::Paranoia not included" do
|
55
|
+
it { should_not respond_to(:before_restore) }
|
56
|
+
it { should_not respond_to(:after_restore) }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "index" do
|
61
|
+
before { ParanoidDocument.create_indexes }
|
62
|
+
after { ParanoidDocument.remove_indexes }
|
63
|
+
subject { ParanoidDocument }
|
64
|
+
|
65
|
+
it_should_behave_like "has an index", { _slugs: 1 }, { unique: true, sparse: true }
|
66
|
+
end
|
67
|
+
|
68
|
+
shared_examples_for "paranoid slugs" do
|
69
|
+
|
70
|
+
context "querying" do
|
71
|
+
|
72
|
+
it "returns paranoid_doc for correct slug" do
|
73
|
+
subject.class.find(subject.slug).should eq(subject)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "delete (callbacks not fired)" do
|
78
|
+
|
79
|
+
before { subject.delete }
|
80
|
+
|
81
|
+
it "retains slug value" do
|
82
|
+
subject.slug.should eq "slug"
|
83
|
+
subject.class.unscoped.find("slug").should eq subject
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context "destroy" do
|
88
|
+
|
89
|
+
before { subject.destroy }
|
90
|
+
|
91
|
+
it "unsets slug value when destroyed" do
|
92
|
+
subject._slugs.should eq []
|
93
|
+
subject.slug.should be_nil
|
94
|
+
end
|
95
|
+
|
96
|
+
it "persists the removed slug" do
|
97
|
+
subject.reload._slugs.should eq []
|
98
|
+
subject.reload.slug.should be_nil
|
99
|
+
end
|
100
|
+
|
101
|
+
it "persists the removed slug in the database" do
|
102
|
+
subject.class.unscoped.exists(_slugs: false).first.should eq subject
|
103
|
+
expect{subject.class.unscoped.find("slug")}.to raise_error(Mongoid::Errors::DocumentNotFound)
|
104
|
+
end
|
105
|
+
|
106
|
+
context "when saving the doc again" do
|
107
|
+
|
108
|
+
before { subject.save }
|
109
|
+
|
110
|
+
it "should have the default slug value" do
|
111
|
+
subject._slugs.should eq []
|
112
|
+
subject.slug.should be_nil
|
113
|
+
end
|
114
|
+
|
115
|
+
it "the slug remains unset in the database" do
|
116
|
+
subject.class.unscoped.exists(_slugs: false).first.should eq subject
|
117
|
+
expect{subject.class.unscoped.find("slug")}.to raise_error(Mongoid::Errors::DocumentNotFound)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context "restore" do
|
123
|
+
|
124
|
+
before do
|
125
|
+
subject.destroy
|
126
|
+
subject.restore
|
127
|
+
end
|
128
|
+
|
129
|
+
it "resets slug value when restored" do
|
130
|
+
subject.slug.should eq "slug"
|
131
|
+
subject.reload.slug.should eq "slug"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context "multiple documents" do
|
136
|
+
|
137
|
+
it "new documents should be able to use the slug of destroyed documents" do
|
138
|
+
subject.slug.should eq "slug"
|
139
|
+
subject.destroy
|
140
|
+
subject.reload.slug.should be_nil
|
141
|
+
other_doc.slug.should eq "slug"
|
142
|
+
subject.restore
|
143
|
+
subject.slug.should eq "slug-1"
|
144
|
+
subject.reload.slug.should eq "slug-1"
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should allow multiple documents to be destroyed without index conflict" do
|
148
|
+
subject.slug.should eq "slug"
|
149
|
+
subject.destroy
|
150
|
+
subject.reload.slug.should be_nil
|
151
|
+
other_doc.slug.should eq "slug"
|
152
|
+
other_doc.destroy
|
153
|
+
other_doc.reload.slug.should be_nil
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
context "non-permanent slug" do
|
159
|
+
subject { paranoid_doc }
|
160
|
+
let(:other_doc) { paranoid_doc_2 }
|
161
|
+
it_behaves_like "paranoid slugs"
|
162
|
+
end
|
163
|
+
|
164
|
+
context "permanent slug" do
|
165
|
+
subject { paranoid_perm }
|
166
|
+
let(:other_doc) { paranoid_perm_2 }
|
167
|
+
it_behaves_like "paranoid slugs"
|
168
|
+
end
|
169
|
+
end
|
data/spec/mongoid/slug_spec.rb
CHANGED
@@ -523,7 +523,7 @@ module Mongoid
|
|
523
523
|
|
524
524
|
context "when slug is not scoped by a reference association" do
|
525
525
|
subject { Book }
|
526
|
-
it_should_behave_like "has an index", { _slugs: 1 }, { unique: true }
|
526
|
+
it_should_behave_like "has an index", { _slugs: 1 }, { unique: true, sparse: true }
|
527
527
|
end
|
528
528
|
|
529
529
|
context "when slug is scoped by a reference association" do
|
@@ -534,7 +534,7 @@ module Mongoid
|
|
534
534
|
context "for subclass scope" do
|
535
535
|
context "when slug is not scoped by a reference association" do
|
536
536
|
subject { BookPolymorphic }
|
537
|
-
it_should_behave_like "has an index", { _type: 1, _slugs: 1 }, { unique: nil }
|
537
|
+
it_should_behave_like "has an index", { _type: 1, _slugs: 1 }, { unique: nil, sparse: nil }
|
538
538
|
end
|
539
539
|
|
540
540
|
context "when slug is scoped by a reference association" do
|
@@ -672,12 +672,12 @@ module Mongoid
|
|
672
672
|
let(:book) { Book.first }
|
673
673
|
|
674
674
|
it "is initially unchanged" do
|
675
|
-
book._slugs_changed?.should
|
675
|
+
book._slugs_changed?.should be_falsey
|
676
676
|
end
|
677
677
|
|
678
678
|
it "tracks changes" do
|
679
679
|
book.slugs = ["Anti Oedipus"]
|
680
|
-
book._slugs_changed?.should
|
680
|
+
book._slugs_changed?.should be_truthy
|
681
681
|
end
|
682
682
|
end
|
683
683
|
|
@@ -1018,25 +1018,5 @@ module Mongoid
|
|
1018
1018
|
end
|
1019
1019
|
|
1020
1020
|
end
|
1021
|
-
|
1022
|
-
context "Mongoid paranoia with mongoid slug model" do
|
1023
|
-
|
1024
|
-
let(:paranoid_doc) {ParanoidDocument.create!(:title => "slug")}
|
1025
|
-
|
1026
|
-
it "returns paranoid_doc for correct slug" do
|
1027
|
-
ParanoidDocument.find(paranoid_doc.slug).should eq(paranoid_doc)
|
1028
|
-
end
|
1029
|
-
|
1030
|
-
it "raises for deleted slug" do
|
1031
|
-
paranoid_doc.delete
|
1032
|
-
expect{ParanoidDocument.find(paranoid_doc.slug)}.to raise_error(Mongoid::Errors::DocumentNotFound)
|
1033
|
-
end
|
1034
|
-
|
1035
|
-
it "returns paranoid_doc for correct restored slug" do
|
1036
|
-
paranoid_doc.delete
|
1037
|
-
ParanoidDocument.deleted.first.restore
|
1038
|
-
ParanoidDocument.find(paranoid_doc.slug).should eq(paranoid_doc)
|
1039
|
-
end
|
1040
|
-
end
|
1041
1021
|
end
|
1042
1022
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,13 +1,19 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
|
1
3
|
begin
|
2
4
|
require 'pry'
|
3
5
|
rescue LoadError
|
4
6
|
end
|
5
7
|
require 'rspec'
|
6
8
|
require 'uuid'
|
7
|
-
require
|
8
|
-
|
9
|
-
require
|
9
|
+
require 'awesome_print'
|
10
|
+
require 'active_support'
|
11
|
+
require 'active_support/deprecation'
|
12
|
+
require 'mongoid'
|
10
13
|
require 'mongoid/paranoia'
|
14
|
+
require 'rspec/its'
|
15
|
+
|
16
|
+
require File.expand_path '../../lib/mongoid/slug', __FILE__
|
11
17
|
|
12
18
|
module Mongoid::Slug::UuidIdStrategy
|
13
19
|
def self.call id
|
@@ -32,7 +38,7 @@ I18n.available_locales = [ :en, :nl ]
|
|
32
38
|
RSpec.configure do |c|
|
33
39
|
c.before(:each) do
|
34
40
|
Mongoid.purge!
|
35
|
-
Mongoid::IdentityMap.clear
|
41
|
+
Mongoid::IdentityMap.clear if defined?(Mongoid::IdentityMap)
|
36
42
|
end
|
37
43
|
|
38
44
|
c.after(:suite) do
|
metadata
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid_slug
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andreas Saebjoernsen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-12-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mongoid
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '3.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '3.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec-its
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: awesome_print
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -133,6 +147,8 @@ files:
|
|
133
147
|
- README.md
|
134
148
|
- lib/mongoid/slug.rb
|
135
149
|
- lib/mongoid/slug/criteria.rb
|
150
|
+
- lib/mongoid/slug/index.rb
|
151
|
+
- lib/mongoid/slug/paranoia.rb
|
136
152
|
- lib/mongoid/slug/slug_id_strategy.rb
|
137
153
|
- lib/mongoid/slug/unique_slug.rb
|
138
154
|
- lib/mongoid/slug/version.rb
|
@@ -155,6 +171,7 @@ files:
|
|
155
171
|
- spec/models/page_slug_localized_custom.rb
|
156
172
|
- spec/models/page_slug_localized_history.rb
|
157
173
|
- spec/models/paranoid_document.rb
|
174
|
+
- spec/models/paranoid_permanent.rb
|
158
175
|
- spec/models/partner.rb
|
159
176
|
- spec/models/person.rb
|
160
177
|
- spec/models/relationship.rb
|
@@ -162,6 +179,8 @@ files:
|
|
162
179
|
- spec/models/subject.rb
|
163
180
|
- spec/models/without_slug.rb
|
164
181
|
- spec/mongoid/criteria_spec.rb
|
182
|
+
- spec/mongoid/index_spec.rb
|
183
|
+
- spec/mongoid/paranoia_spec.rb
|
165
184
|
- spec/mongoid/slug_spec.rb
|
166
185
|
- spec/mongoid/slug_spec.rb.b00
|
167
186
|
- spec/shared/indexes.rb
|
@@ -170,7 +189,9 @@ homepage: https://github.com/digitalplaywright/mongoid-slug
|
|
170
189
|
licenses:
|
171
190
|
- MIT
|
172
191
|
metadata: {}
|
173
|
-
post_install_message:
|
192
|
+
post_install_message: "[NOTICE]: Deprecated gem name. The name of this gem will be
|
193
|
+
changing from 'mongoid_slug' to 'mongoid-slug' (notice the hyphen). To ensure you
|
194
|
+
are using the correct version of this gem, please use 'mongoid-slug'."
|
174
195
|
rdoc_options: []
|
175
196
|
require_paths:
|
176
197
|
- lib
|
@@ -209,6 +230,7 @@ test_files:
|
|
209
230
|
- spec/models/page_slug_localized_custom.rb
|
210
231
|
- spec/models/page_slug_localized_history.rb
|
211
232
|
- spec/models/paranoid_document.rb
|
233
|
+
- spec/models/paranoid_permanent.rb
|
212
234
|
- spec/models/partner.rb
|
213
235
|
- spec/models/person.rb
|
214
236
|
- spec/models/relationship.rb
|
@@ -216,7 +238,10 @@ test_files:
|
|
216
238
|
- spec/models/subject.rb
|
217
239
|
- spec/models/without_slug.rb
|
218
240
|
- spec/mongoid/criteria_spec.rb
|
241
|
+
- spec/mongoid/index_spec.rb
|
242
|
+
- spec/mongoid/paranoia_spec.rb
|
219
243
|
- spec/mongoid/slug_spec.rb
|
220
244
|
- spec/mongoid/slug_spec.rb.b00
|
221
245
|
- spec/shared/indexes.rb
|
222
246
|
- spec/spec_helper.rb
|
247
|
+
has_rdoc:
|