mongoid-slug 6.0.1 → 7.0.0
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.
- checksums.yaml +4 -4
- data/README.md +34 -3
- data/lib/mongoid/slug/criteria.rb +10 -6
- data/lib/mongoid/slug/index_builder.rb +2 -0
- data/lib/mongoid/slug/railtie.rb +2 -0
- data/lib/mongoid/slug/slug_id_strategy.rb +2 -0
- data/lib/mongoid/slug/unique_slug.rb +8 -9
- data/lib/mongoid/slug/version.rb +4 -2
- data/lib/mongoid/slug.rb +15 -10
- data/lib/mongoid_slug.rb +2 -0
- data/lib/tasks/mongoid_slug.rake +3 -1
- metadata +9 -168
- data/spec/models/alias.rb +0 -6
- data/spec/models/article.rb +0 -9
- data/spec/models/artist.rb +0 -8
- data/spec/models/artwork.rb +0 -10
- data/spec/models/author.rb +0 -15
- data/spec/models/author_polymorphic.rb +0 -15
- data/spec/models/book.rb +0 -12
- data/spec/models/book_polymorphic.rb +0 -12
- data/spec/models/caption.rb +0 -17
- data/spec/models/entity.rb +0 -11
- data/spec/models/friend.rb +0 -7
- data/spec/models/incorrect_slug_persistence.rb +0 -9
- data/spec/models/integer_id.rb +0 -9
- data/spec/models/magazine.rb +0 -7
- data/spec/models/page.rb +0 -9
- data/spec/models/page_localize.rb +0 -9
- data/spec/models/page_slug_localized.rb +0 -9
- data/spec/models/page_slug_localized_custom.rb +0 -10
- data/spec/models/page_slug_localized_history.rb +0 -9
- data/spec/models/partner.rb +0 -7
- data/spec/models/person.rb +0 -12
- data/spec/models/relationship.rb +0 -8
- data/spec/models/string_id.rb +0 -9
- data/spec/models/subject.rb +0 -7
- data/spec/models/without_slug.rb +0 -5
- data/spec/mongoid/criteria_spec.rb +0 -207
- data/spec/mongoid/index_builder_spec.rb +0 -105
- data/spec/mongoid/slug_spec.rb +0 -1175
- data/spec/shared/indexes.rb +0 -41
- data/spec/spec_helper.rb +0 -61
- data/spec/tasks/mongoid_slug_rake_spec.rb +0 -73
data/spec/mongoid/slug_spec.rb
DELETED
@@ -1,1175 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Mongoid
|
4
|
-
describe Slug do
|
5
|
-
let(:book) do
|
6
|
-
Book.create(title: 'A Thousand Plateaus')
|
7
|
-
end
|
8
|
-
|
9
|
-
context 'special cases' do
|
10
|
-
it 'slugs are not be generated from invalid documents' do
|
11
|
-
# this will fail now
|
12
|
-
x = IncorrectSlugPersistence.create!(name: 'test')
|
13
|
-
expect(x.slug).to eq('test')
|
14
|
-
|
15
|
-
# I believe this will now fail
|
16
|
-
x.name = 'te'
|
17
|
-
x.valid?
|
18
|
-
expect(x.slug).not_to eq('te')
|
19
|
-
|
20
|
-
# I believe this will persist the 'te'
|
21
|
-
x.name = 'testb'
|
22
|
-
x.save!
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'has no slugs for blank strings' do
|
26
|
-
book = Book.create!(title: '')
|
27
|
-
expect(book.reload.slugs).to be nil
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'has no slugs for dashes' do
|
31
|
-
book = Book.create!(title: '-')
|
32
|
-
expect(book.reload.slugs).to be nil
|
33
|
-
end
|
34
|
-
|
35
|
-
it 'has no slugs for underscores' do
|
36
|
-
book = Book.create!(title: '_')
|
37
|
-
expect(book.reload.slugs).to be nil
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'has no slugs for nil strings' do
|
41
|
-
book = Book.create!
|
42
|
-
expect(book.reload.slugs).to be nil
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'works for multiple nils' do
|
46
|
-
expect do
|
47
|
-
2.times do
|
48
|
-
Book.create!
|
49
|
-
end
|
50
|
-
end.to_not raise_error # Mongo::Error::OperationFailure
|
51
|
-
expect(Book.all.map(&:slug)).to eq Book.all.map(&:id).map(&:to_s)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
context 'when option skip_id_check is used with UUID _id ' do
|
56
|
-
let(:entity0) do
|
57
|
-
Entity.create(_id: UUID.generate, name: 'Pelham 1 2 3', user_edited_variation: 'pelham-1-2-3')
|
58
|
-
end
|
59
|
-
let(:entity1) do
|
60
|
-
Entity.create(_id: UUID.generate, name: 'Jackson 5', user_edited_variation: 'jackson-5')
|
61
|
-
end
|
62
|
-
let(:entity2) do
|
63
|
-
Entity.create(_id: UUID.generate, name: 'Jackson 5', user_edited_variation: 'jackson-5')
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'generates a unique slug by appending a counter to duplicate text' do
|
67
|
-
expect(entity0.to_param).to eql 'pelham-1-2-3'
|
68
|
-
|
69
|
-
5.times do |x|
|
70
|
-
dup = Entity.create(_id: UUID.generate, name: entity0.name, user_edited_variation: entity0.user_edited_variation)
|
71
|
-
expect(dup.to_param).to eql "pelham-1-2-3-#{x.succ}"
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
it 'allows the user to edit the sluggable field' do
|
76
|
-
expect(entity1.to_param).to eql 'jackson-5'
|
77
|
-
expect(entity2.to_param).to eql 'jackson-5-1'
|
78
|
-
entity2.user_edited_variation = 'jackson-5-indiana'
|
79
|
-
entity2.save
|
80
|
-
expect(entity2.to_param).to eql 'jackson-5-indiana'
|
81
|
-
end
|
82
|
-
|
83
|
-
it 'allows users to edit the sluggable field' do
|
84
|
-
expect(entity1.to_param).to eql 'jackson-5'
|
85
|
-
expect(entity2.to_param).to eql 'jackson-5-1'
|
86
|
-
entity2.user_edited_variation = 'jackson-5-indiana'
|
87
|
-
entity2.save
|
88
|
-
expect(entity2.to_param).to eql 'jackson-5-indiana'
|
89
|
-
end
|
90
|
-
|
91
|
-
it 'it restores the slug if the editing user tries to use an existing slug' do
|
92
|
-
expect(entity1.to_param).to eql 'jackson-5'
|
93
|
-
expect(entity2.to_param).to eql 'jackson-5-1'
|
94
|
-
entity2.user_edited_variation = 'jackson-5'
|
95
|
-
entity2.save
|
96
|
-
expect(entity2.to_param).to eql 'jackson-5-1'
|
97
|
-
end
|
98
|
-
|
99
|
-
it 'does not force an appended counter on a plain string' do
|
100
|
-
entity = Entity.create(_id: UUID.generate, name: 'Adele', user_edited_variation: 'adele')
|
101
|
-
expect(entity.to_param).to eql 'adele'
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
context 'when the object is top-level' do
|
106
|
-
it 'generates a slug' do
|
107
|
-
expect(book.to_param).to eql 'a-thousand-plateaus'
|
108
|
-
end
|
109
|
-
|
110
|
-
it 'updates the slug' do
|
111
|
-
book.title = 'Anti Oedipus'
|
112
|
-
book.save
|
113
|
-
expect(book.to_param).to eql 'anti-oedipus'
|
114
|
-
end
|
115
|
-
|
116
|
-
it 'generates a unique slug by appending a counter to duplicate text' do
|
117
|
-
15.times do |x|
|
118
|
-
dup = Book.create(title: book.title)
|
119
|
-
expect(dup.to_param).to eql "a-thousand-plateaus-#{x + 1}"
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
it 'does not allow a BSON::ObjectId as use for a slug' do
|
124
|
-
bson_id = Mongoid::Compatibility::Version.mongoid3? ? Moped::BSON::ObjectId.new.to_s : BSON::ObjectId.new.to_s
|
125
|
-
bad = Book.create(title: bson_id)
|
126
|
-
expect(bad.slugs).not_to include(bson_id)
|
127
|
-
end
|
128
|
-
|
129
|
-
it 'does not update slug if slugged fields have not changed' do
|
130
|
-
book.save
|
131
|
-
expect(book.to_param).to eql 'a-thousand-plateaus'
|
132
|
-
end
|
133
|
-
|
134
|
-
it 'does not change slug if slugged fields have changed but generated slug is identical' do
|
135
|
-
book.title = 'a thousand plateaus'
|
136
|
-
book.save
|
137
|
-
expect(book.to_param).to eql 'a-thousand-plateaus'
|
138
|
-
end
|
139
|
-
|
140
|
-
context 'using find' do
|
141
|
-
it 'finds by id as string' do
|
142
|
-
expect(Book.find(book.id.to_s)).to eql book
|
143
|
-
end
|
144
|
-
|
145
|
-
it 'finds by id as array of strings' do
|
146
|
-
expect(Book.find([book.id.to_s])).to eql [book]
|
147
|
-
end
|
148
|
-
|
149
|
-
it 'finds by id as BSON::ObjectId' do
|
150
|
-
expect(Book.find(book.id)).to eql book
|
151
|
-
end
|
152
|
-
|
153
|
-
it 'finds by id as an array of BSON::ObjectIds' do
|
154
|
-
expect(Book.find([book.id])).to eql [book]
|
155
|
-
end
|
156
|
-
|
157
|
-
it 'returns an empty array if given an empty array' do
|
158
|
-
expect(Book.find([])).to eql []
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
context 'when the object is embedded' do
|
164
|
-
let(:subject) do
|
165
|
-
book.subjects.create(name: 'Psychoanalysis')
|
166
|
-
end
|
167
|
-
|
168
|
-
it 'generates a slug' do
|
169
|
-
expect(subject.to_param).to eql 'psychoanalysis'
|
170
|
-
end
|
171
|
-
|
172
|
-
it 'updates the slug' do
|
173
|
-
subject.name = 'Schizoanalysis'
|
174
|
-
subject.save
|
175
|
-
expect(subject.to_param).to eql 'schizoanalysis'
|
176
|
-
end
|
177
|
-
|
178
|
-
it 'generates a unique slug by appending a counter to duplicate text' do
|
179
|
-
dup = book.subjects.create(name: subject.name)
|
180
|
-
expect(dup.to_param).to eql 'psychoanalysis-1'
|
181
|
-
end
|
182
|
-
|
183
|
-
it 'does not allow a BSON::ObjectId as use for a slug' do
|
184
|
-
bad = book.subjects.create(name: '4ea0389f0364313d79104fb3')
|
185
|
-
expect(bad.slugs).not_to eql '4ea0389f0364313d79104fb3'
|
186
|
-
end
|
187
|
-
|
188
|
-
it 'does not update slug if slugged fields have not changed' do
|
189
|
-
subject.save
|
190
|
-
expect(subject.to_param).to eql 'psychoanalysis'
|
191
|
-
end
|
192
|
-
|
193
|
-
it 'does not change slug if slugged fields have changed but generated slug is identical' do
|
194
|
-
subject.name = 'PSYCHOANALYSIS'
|
195
|
-
expect(subject.to_param).to eql 'psychoanalysis'
|
196
|
-
end
|
197
|
-
|
198
|
-
context 'using find' do
|
199
|
-
it 'finds by id as string' do
|
200
|
-
expect(book.subjects.find(subject.id.to_s)).to eql subject
|
201
|
-
end
|
202
|
-
|
203
|
-
it 'finds by id as array of strings' do
|
204
|
-
expect(book.subjects.find([subject.id.to_s])).to eql [subject]
|
205
|
-
end
|
206
|
-
|
207
|
-
it 'finds by id as BSON::ObjectId' do
|
208
|
-
expect(book.subjects.find(subject.id)).to eql subject
|
209
|
-
end
|
210
|
-
|
211
|
-
it 'finds by id as an array of BSON::ObjectIds' do
|
212
|
-
expect(book.subjects.find([subject.id])).to eql [subject]
|
213
|
-
end
|
214
|
-
|
215
|
-
it 'returns an empty array if given an empty array' do
|
216
|
-
expect(book.subjects.find([])).to eql []
|
217
|
-
end
|
218
|
-
end
|
219
|
-
end
|
220
|
-
|
221
|
-
context 'when the object is embedded in another embedded object' do
|
222
|
-
let(:person) do
|
223
|
-
Person.create(name: 'John Doe')
|
224
|
-
end
|
225
|
-
|
226
|
-
let(:relationship) do
|
227
|
-
person.relationships.create(name: 'Engagement')
|
228
|
-
end
|
229
|
-
|
230
|
-
let(:partner) do
|
231
|
-
relationship.partners.create(name: 'Jane Smith')
|
232
|
-
end
|
233
|
-
|
234
|
-
it 'generates a slug' do
|
235
|
-
expect(partner.to_param).to eql 'jane-smith'
|
236
|
-
end
|
237
|
-
|
238
|
-
it 'updates the slug' do
|
239
|
-
partner.name = 'Jane Doe'
|
240
|
-
partner.save
|
241
|
-
expect(partner.to_param).to eql 'jane-doe'
|
242
|
-
end
|
243
|
-
|
244
|
-
it 'generates a unique slug by appending a counter to duplicate text' do
|
245
|
-
dup = relationship.partners.create(name: partner.name)
|
246
|
-
expect(dup.to_param).to eql 'jane-smith-1'
|
247
|
-
end
|
248
|
-
|
249
|
-
it 'does not allow a BSON::ObjectId as use for a slug' do
|
250
|
-
bad = relationship.partners.create(name: '4ea0389f0364313d79104fb3')
|
251
|
-
expect(bad.slugs).not_to eql '4ea0389f0364313d79104fb3'
|
252
|
-
end
|
253
|
-
|
254
|
-
it 'does not update slug if slugged fields have not changed' do
|
255
|
-
partner.save
|
256
|
-
expect(partner.to_param).to eql 'jane-smith'
|
257
|
-
end
|
258
|
-
|
259
|
-
it 'does not change slug if slugged fields have changed but generated slug is identical' do
|
260
|
-
partner.name = 'JANE SMITH'
|
261
|
-
expect(partner.to_param).to eql 'jane-smith'
|
262
|
-
end
|
263
|
-
|
264
|
-
it 'scopes by parent object' do
|
265
|
-
affair = person.relationships.create(name: 'Affair')
|
266
|
-
lover = affair.partners.create(name: partner.name)
|
267
|
-
expect(lover.to_param).to eql partner.to_param
|
268
|
-
end
|
269
|
-
|
270
|
-
context 'using find' do
|
271
|
-
it 'finds by id as string' do
|
272
|
-
expect(relationship.partners.find(partner.id.to_s)).to eql partner
|
273
|
-
end
|
274
|
-
|
275
|
-
it 'finds by id as array of strings' do
|
276
|
-
expect(relationship.partners.find([partner.id.to_s])).to eql [partner]
|
277
|
-
end
|
278
|
-
|
279
|
-
it 'finds by id as BSON::ObjectId' do
|
280
|
-
expect(relationship.partners.find(partner.id)).to eql partner
|
281
|
-
end
|
282
|
-
|
283
|
-
it 'finds by id as an array of BSON::ObjectIds' do
|
284
|
-
expect(relationship.partners.find([partner.id])).to eql [partner]
|
285
|
-
end
|
286
|
-
|
287
|
-
it 'returns an empty array if given an empty array' do
|
288
|
-
expect(relationship.partners.find([])).to eql []
|
289
|
-
end
|
290
|
-
end
|
291
|
-
end
|
292
|
-
|
293
|
-
context 'when the slug is composed of multiple fields' do
|
294
|
-
let!(:author) do
|
295
|
-
Author.create(
|
296
|
-
first_name: 'Gilles',
|
297
|
-
last_name: 'Deleuze'
|
298
|
-
)
|
299
|
-
end
|
300
|
-
|
301
|
-
it 'generates a slug' do
|
302
|
-
expect(author.to_param).to eql 'gilles-deleuze'
|
303
|
-
end
|
304
|
-
|
305
|
-
it 'updates the slug' do
|
306
|
-
author.first_name = 'Félix'
|
307
|
-
author.last_name = 'Guattari'
|
308
|
-
author.save
|
309
|
-
expect(author.to_param).to eql 'felix-guattari'
|
310
|
-
end
|
311
|
-
|
312
|
-
it 'generates a unique slug by appending a counter to duplicate text' do
|
313
|
-
dup = Author.create(
|
314
|
-
first_name: author.first_name,
|
315
|
-
last_name: author.last_name
|
316
|
-
)
|
317
|
-
expect(dup.to_param).to eql 'gilles-deleuze-1'
|
318
|
-
|
319
|
-
dup2 = Author.create(
|
320
|
-
first_name: author.first_name,
|
321
|
-
last_name: author.last_name
|
322
|
-
)
|
323
|
-
|
324
|
-
dup.save
|
325
|
-
expect(dup2.to_param).to eql 'gilles-deleuze-2'
|
326
|
-
end
|
327
|
-
|
328
|
-
it 'does not allow a BSON::ObjectId as use for a slug' do
|
329
|
-
bad = Author.create(first_name: '4ea0389f0364',
|
330
|
-
last_name: '313d79104fb3')
|
331
|
-
expect(bad.to_param).not_to eql '4ea0389f0364313d79104fb3'
|
332
|
-
end
|
333
|
-
|
334
|
-
it 'does not update slug if slugged fields have changed but generated slug is identical' do
|
335
|
-
author.last_name = 'DELEUZE'
|
336
|
-
author.save
|
337
|
-
expect(author.to_param).to eql 'gilles-deleuze'
|
338
|
-
end
|
339
|
-
end
|
340
|
-
|
341
|
-
context 'when :as is passed as an argument' do
|
342
|
-
let!(:person) do
|
343
|
-
Person.create(name: 'John Doe')
|
344
|
-
end
|
345
|
-
|
346
|
-
it 'sets an alternative slug field name' do
|
347
|
-
expect(person).to respond_to(:_slugs)
|
348
|
-
expect(person.slugs).to eql ['john-doe']
|
349
|
-
end
|
350
|
-
|
351
|
-
it 'defines #slug' do
|
352
|
-
expect(person).to respond_to :slugs
|
353
|
-
end
|
354
|
-
|
355
|
-
it 'defines #slug_changed?' do
|
356
|
-
expect(person).to respond_to :_slugs_changed?
|
357
|
-
end
|
358
|
-
|
359
|
-
it 'defines #slug_was' do
|
360
|
-
expect(person).to respond_to :_slugs_was
|
361
|
-
end
|
362
|
-
end
|
363
|
-
|
364
|
-
context 'when :permanent is passed as an argument' do
|
365
|
-
let(:person) do
|
366
|
-
Person.create(name: 'John Doe')
|
367
|
-
end
|
368
|
-
|
369
|
-
it 'does not update the slug when the slugged fields change' do
|
370
|
-
person.name = 'Jane Doe'
|
371
|
-
person.save
|
372
|
-
expect(person.to_param).to eql 'john-doe'
|
373
|
-
end
|
374
|
-
end
|
375
|
-
|
376
|
-
context 'when :history is passed as an argument' do
|
377
|
-
context 'true' do
|
378
|
-
let(:book) do
|
379
|
-
Book.create(title: 'Book Title')
|
380
|
-
end
|
381
|
-
|
382
|
-
before(:each) do
|
383
|
-
book.title = 'Other Book Title'
|
384
|
-
book.save
|
385
|
-
end
|
386
|
-
|
387
|
-
it "saves the old slug in the owner's history" do
|
388
|
-
expect(book.slugs).to include('book-title')
|
389
|
-
end
|
390
|
-
|
391
|
-
it 'generates a unique slug by appending a counter to duplicate text' do
|
392
|
-
dup = Book.create(title: 'Book Title')
|
393
|
-
expect(dup.to_param).to eql 'book-title-1'
|
394
|
-
end
|
395
|
-
|
396
|
-
it 'does not allow a BSON::ObjectId as use for a slug' do
|
397
|
-
bad = Book.create(title: '4ea0389f0364313d79104fb3')
|
398
|
-
expect(bad.to_param).not_to eql '4ea0389f0364313d79104fb3'
|
399
|
-
end
|
400
|
-
|
401
|
-
it 'ensures no duplicate values are stored in history' do
|
402
|
-
book.update_attributes title: 'Book Title'
|
403
|
-
book.update_attributes title: 'Foo'
|
404
|
-
expect(book.slugs.find_all { |slug| slug == 'book-title' }.size).to eql 1
|
405
|
-
end
|
406
|
-
end
|
407
|
-
context 'false' do
|
408
|
-
let(:author) do
|
409
|
-
Author.create(first_name: 'Gilles', last_name: 'Deleuze')
|
410
|
-
end
|
411
|
-
|
412
|
-
before(:each) do
|
413
|
-
author.first_name = 'John'
|
414
|
-
author.save
|
415
|
-
end
|
416
|
-
|
417
|
-
it "does not save the old slug in the owner's history" do
|
418
|
-
expect(author.slugs.count).to eq 1
|
419
|
-
expect(author.slugs).to_not include('gilles-deleuze')
|
420
|
-
end
|
421
|
-
end
|
422
|
-
end
|
423
|
-
|
424
|
-
context 'when slug is scoped by a reference association' do
|
425
|
-
let(:author) do
|
426
|
-
book.authors.create(first_name: 'Gilles', last_name: 'Deleuze')
|
427
|
-
end
|
428
|
-
|
429
|
-
it 'scopes by parent object' do
|
430
|
-
book2 = Book.create(title: 'Anti Oedipus')
|
431
|
-
dup = book2.authors.create(
|
432
|
-
first_name: author.first_name,
|
433
|
-
last_name: author.last_name
|
434
|
-
)
|
435
|
-
expect(dup.to_param).to eql author.to_param
|
436
|
-
end
|
437
|
-
|
438
|
-
it 'generates a unique slug by appending a counter to duplicate text' do
|
439
|
-
dup = book.authors.create(
|
440
|
-
first_name: author.first_name,
|
441
|
-
last_name: author.last_name
|
442
|
-
)
|
443
|
-
expect(dup.to_param).to eql 'gilles-deleuze-1'
|
444
|
-
end
|
445
|
-
|
446
|
-
it 'does not allow a BSON::ObjectId as use for a slug' do
|
447
|
-
bad = book.authors.create(first_name: '4ea0389f0364',
|
448
|
-
last_name: '313d79104fb3')
|
449
|
-
expect(bad.to_param).not_to eql '4ea0389f0364313d79104fb3'
|
450
|
-
end
|
451
|
-
|
452
|
-
context 'with an irregular association name' do
|
453
|
-
let(:character) do
|
454
|
-
# well we've got to make up something... :-)
|
455
|
-
author.characters.create(name: 'Oedipus')
|
456
|
-
end
|
457
|
-
|
458
|
-
let!(:author2) do
|
459
|
-
Author.create(
|
460
|
-
first_name: 'Sophocles',
|
461
|
-
last_name: 'son of Sophilos'
|
462
|
-
)
|
463
|
-
end
|
464
|
-
|
465
|
-
it 'scopes by parent object provided that inverse_of is specified' do
|
466
|
-
dup = author2.characters.create(name: character.name)
|
467
|
-
expect(dup.to_param).to eql character.to_param
|
468
|
-
end
|
469
|
-
end
|
470
|
-
end
|
471
|
-
|
472
|
-
context "when slug is scoped by one of the class's own fields" do
|
473
|
-
let!(:magazine) do
|
474
|
-
Magazine.create(title: 'Big Weekly', publisher_id: 'abc123')
|
475
|
-
end
|
476
|
-
|
477
|
-
it 'should scope by local field' do
|
478
|
-
expect(magazine.to_param).to eql 'big-weekly'
|
479
|
-
magazine2 = Magazine.create(title: 'Big Weekly', publisher_id: 'def456')
|
480
|
-
expect(magazine2.to_param).to eql magazine.to_param
|
481
|
-
end
|
482
|
-
|
483
|
-
it 'should generate a unique slug by appending a counter to duplicate text' do
|
484
|
-
dup = Magazine.create(title: 'Big Weekly', publisher_id: 'abc123')
|
485
|
-
expect(dup.to_param).to eql 'big-weekly-1'
|
486
|
-
end
|
487
|
-
|
488
|
-
it 'does not allow a BSON::ObjectId as use for a slug' do
|
489
|
-
bad = Magazine.create(title: '4ea0389f0364313d79104fb3', publisher_id: 'abc123')
|
490
|
-
expect(bad.to_param).not_to eql '4ea0389f0364313d79104fb3'
|
491
|
-
end
|
492
|
-
end
|
493
|
-
|
494
|
-
context 'when #slug is given a block' do
|
495
|
-
let(:caption) do
|
496
|
-
Caption.create(my_identity: 'Edward Hopper (American, 1882-1967)',
|
497
|
-
title: 'Soir Bleu, 1914',
|
498
|
-
medium: 'Oil on Canvas')
|
499
|
-
end
|
500
|
-
|
501
|
-
it 'generates a slug' do
|
502
|
-
expect(caption.to_param).to eql 'edward-hopper-soir-bleu-1914'
|
503
|
-
end
|
504
|
-
|
505
|
-
it 'updates the slug' do
|
506
|
-
caption.title = 'Road in Maine, 1914'
|
507
|
-
caption.save
|
508
|
-
expect(caption.to_param).to eql 'edward-hopper-road-in-maine-1914'
|
509
|
-
end
|
510
|
-
|
511
|
-
it 'does not change slug if slugged fields have changed but generated slug is identical' do
|
512
|
-
caption.my_identity = 'Edward Hopper'
|
513
|
-
caption.save
|
514
|
-
expect(caption.to_param).to eql 'edward-hopper-soir-bleu-1914'
|
515
|
-
end
|
516
|
-
end
|
517
|
-
|
518
|
-
context 'when block is configured globally' do
|
519
|
-
before do
|
520
|
-
Mongoid::Slug.configure do |c|
|
521
|
-
c.slug do |cur_obj|
|
522
|
-
slug = cur_obj.slug_builder
|
523
|
-
"#{slug}-#{cur_obj.id}".to_url
|
524
|
-
end
|
525
|
-
end
|
526
|
-
end
|
527
|
-
|
528
|
-
after do
|
529
|
-
# Remove global configuration to avoid affect on
|
530
|
-
# other specs run after this spec
|
531
|
-
Mongoid::Slug.default_slug = nil
|
532
|
-
expect(Mongoid::Slug.default_slug).to be_nil
|
533
|
-
end
|
534
|
-
|
535
|
-
it 'generates a slug' do
|
536
|
-
expect(Mongoid::Slug.default_slug).to be_present
|
537
|
-
class Person
|
538
|
-
include Mongoid::Document
|
539
|
-
include Mongoid::Slug
|
540
|
-
|
541
|
-
field :name
|
542
|
-
slug :name
|
543
|
-
end
|
544
|
-
|
545
|
-
person = Person.create(name: 'John')
|
546
|
-
expect(person.to_param).to eql "john-#{person.id}"
|
547
|
-
end
|
548
|
-
|
549
|
-
it 'can be overridden at model level' do
|
550
|
-
expect(Mongoid::Slug.default_slug).to be_present
|
551
|
-
class Person
|
552
|
-
include Mongoid::Document
|
553
|
-
include Mongoid::Slug
|
554
|
-
|
555
|
-
field :name
|
556
|
-
slug :name do |cur_object|
|
557
|
-
cur_object.slug_builder.to_url
|
558
|
-
end
|
559
|
-
end
|
560
|
-
|
561
|
-
person = Person.create(name: 'John')
|
562
|
-
expect(person.to_param).to eql 'john'
|
563
|
-
end
|
564
|
-
end
|
565
|
-
|
566
|
-
context 'when slugged field contains non-ASCII characters' do
|
567
|
-
it 'slugs Cyrillic characters' do
|
568
|
-
book.title = 'Капитал'
|
569
|
-
book.save
|
570
|
-
expect(book.to_param).to eql 'kapital'
|
571
|
-
end
|
572
|
-
|
573
|
-
it 'slugs Greek characters' do
|
574
|
-
book.title = 'Ελλάδα'
|
575
|
-
book.save
|
576
|
-
expect(book.to_param).to eql 'ellada'
|
577
|
-
end
|
578
|
-
|
579
|
-
it 'slugs Chinese characters' do
|
580
|
-
book.title = '中文'
|
581
|
-
book.save
|
582
|
-
expect(book.to_param).to eql 'zhong-wen'
|
583
|
-
end
|
584
|
-
|
585
|
-
it 'slugs non-ASCII Latin characters' do
|
586
|
-
book.title = 'Paul Cézanne'
|
587
|
-
book.save
|
588
|
-
expect(book.to_param).to eql 'paul-cezanne'
|
589
|
-
end
|
590
|
-
end
|
591
|
-
|
592
|
-
context 'when slug is not scoped by a reference association' do
|
593
|
-
subject { Book }
|
594
|
-
it_should_behave_like 'has an index', { _slugs: 1 }, unique: true, sparse: true
|
595
|
-
end
|
596
|
-
|
597
|
-
context 'with a value exceeding mongodb max index key' do
|
598
|
-
if Mongoid::Compatibility::Version.mongoid5_or_newer?
|
599
|
-
xit 'errors with a model without a max length' do
|
600
|
-
expect do
|
601
|
-
Book.create!(title: 't' * 1025)
|
602
|
-
end.to raise_error Mongo::Error::OperationFailure, /key too large to index/
|
603
|
-
end
|
604
|
-
elsif Mongoid::Compatibility::Version.mongoid4?
|
605
|
-
xit 'errors with a model without a max length' do
|
606
|
-
expect do
|
607
|
-
Book.create!(title: 't' * 1025)
|
608
|
-
end.to raise_error Moped::Errors::OperationFailure, /key too large to index/
|
609
|
-
end
|
610
|
-
end
|
611
|
-
|
612
|
-
it 'succeeds with a model with a max length' do
|
613
|
-
expect do
|
614
|
-
author = Author.create!(last_name: 't' * 1025)
|
615
|
-
expect(author.slug.length).to eq 256
|
616
|
-
end.to_not raise_error
|
617
|
-
end
|
618
|
-
end
|
619
|
-
|
620
|
-
context 'when slug is scoped by a reference association' do
|
621
|
-
subject { Author }
|
622
|
-
it_should_behave_like 'does not have an index', _slugs: 1
|
623
|
-
end
|
624
|
-
|
625
|
-
context 'for subclass scope' do
|
626
|
-
context 'when slug is not scoped by a reference association' do
|
627
|
-
subject { BookPolymorphic }
|
628
|
-
it_should_behave_like 'has an index', { _type: 1, _slugs: 1 }, unique: nil, sparse: nil
|
629
|
-
end
|
630
|
-
|
631
|
-
context 'when slug is scoped by a reference association' do
|
632
|
-
subject { AuthorPolymorphic }
|
633
|
-
it_should_behave_like 'does not have an index', _type: 1, _slugs: 1
|
634
|
-
end
|
635
|
-
|
636
|
-
context 'when the object has STI' do
|
637
|
-
it 'scopes by the subclass' do
|
638
|
-
b = BookPolymorphic.create!(title: 'Book')
|
639
|
-
expect(b.slug).to eq('book')
|
640
|
-
|
641
|
-
b2 = BookPolymorphic.create!(title: 'Book')
|
642
|
-
expect(b2.slug).to eq('book-1')
|
643
|
-
|
644
|
-
c = ComicBookPolymorphic.create!(title: 'Book')
|
645
|
-
expect(c.slug).to eq('book')
|
646
|
-
|
647
|
-
c2 = ComicBookPolymorphic.create!(title: 'Book')
|
648
|
-
expect(c2.slug).to eq('book-1')
|
649
|
-
|
650
|
-
expect(BookPolymorphic.find('book')).to eq(b)
|
651
|
-
expect(BookPolymorphic.find('book-1')).to eq(b2)
|
652
|
-
expect(ComicBookPolymorphic.find('book')).to eq(c)
|
653
|
-
expect(ComicBookPolymorphic.find('book-1')).to eq(c2)
|
654
|
-
end
|
655
|
-
end
|
656
|
-
end
|
657
|
-
end
|
658
|
-
|
659
|
-
context 'for reserved words' do
|
660
|
-
context 'when the :reserve option is used on the model' do
|
661
|
-
it 'does not use the reserved slugs' do
|
662
|
-
friend1 = Friend.create(name: 'foo')
|
663
|
-
expect(friend1.slugs).not_to include('foo')
|
664
|
-
expect(friend1.slugs).to include('foo-1')
|
665
|
-
|
666
|
-
friend2 = Friend.create(name: 'bar')
|
667
|
-
expect(friend2.slugs).not_to include('bar')
|
668
|
-
expect(friend2.slugs).to include('bar-1')
|
669
|
-
|
670
|
-
friend3 = Friend.create(name: 'en')
|
671
|
-
expect(friend3.slugs).not_to include('en')
|
672
|
-
expect(friend3.slugs).to include('en-1')
|
673
|
-
end
|
674
|
-
|
675
|
-
it 'should start with concatenation -1' do
|
676
|
-
friend1 = Friend.create(name: 'foo')
|
677
|
-
expect(friend1.slugs).to include('foo-1')
|
678
|
-
friend2 = Friend.create(name: 'foo')
|
679
|
-
expect(friend2.slugs).to include('foo-2')
|
680
|
-
end
|
681
|
-
|
682
|
-
%w[new edit].each do |word|
|
683
|
-
it "should overwrite the default reserved words allowing the word '#{word}'" do
|
684
|
-
friend = Friend.create(name: word)
|
685
|
-
expect(friend.slugs).to include word
|
686
|
-
end
|
687
|
-
end
|
688
|
-
end
|
689
|
-
context 'when the model does not have any reserved words set' do
|
690
|
-
%w[new edit].each do |word|
|
691
|
-
it "does not use the default reserved word '#{word}'" do
|
692
|
-
book = Book.create(title: word)
|
693
|
-
expect(book.slugs).not_to include word
|
694
|
-
expect(book.slugs).to include("#{word}-1")
|
695
|
-
end
|
696
|
-
end
|
697
|
-
end
|
698
|
-
|
699
|
-
context 'when the object has STI' do
|
700
|
-
it 'scopes by the superclass' do
|
701
|
-
book = Book.create(title: 'Anti Oedipus')
|
702
|
-
comic_book = ComicBook.create(title: 'Anti Oedipus')
|
703
|
-
expect(comic_book.slugs).not_to eql(book.slugs)
|
704
|
-
end
|
705
|
-
|
706
|
-
it 'scopes by the subclass' do
|
707
|
-
book = BookPolymorphic.create(title: 'Anti Oedipus')
|
708
|
-
comic_book = ComicBookPolymorphic.create(title: 'Anti Oedipus')
|
709
|
-
expect(comic_book.slugs).to eql(book.slugs)
|
710
|
-
|
711
|
-
expect(BookPolymorphic.find(book.slug)).to eq(book)
|
712
|
-
expect(ComicBookPolymorphic.find(comic_book.slug)).to eq(comic_book)
|
713
|
-
end
|
714
|
-
end
|
715
|
-
|
716
|
-
context 'when slug defined on alias of field' do
|
717
|
-
it 'should use accessor, not alias' do
|
718
|
-
pseudonim = Alias.create(author_name: 'Max Stirner')
|
719
|
-
expect(pseudonim.slugs).to include('max-stirner')
|
720
|
-
end
|
721
|
-
end
|
722
|
-
|
723
|
-
describe '#to_param' do
|
724
|
-
context 'when called on a new record' do
|
725
|
-
let(:book) { Book.new }
|
726
|
-
|
727
|
-
it 'should return nil' do
|
728
|
-
expect(book.to_param).to eq book._id.to_s
|
729
|
-
end
|
730
|
-
|
731
|
-
it 'should not persist the record' do
|
732
|
-
book.to_param
|
733
|
-
expect(book).not_to be_persisted
|
734
|
-
end
|
735
|
-
end
|
736
|
-
|
737
|
-
context 'when called on an existing record with no slug' do
|
738
|
-
let!(:book_no_slug) do
|
739
|
-
if Mongoid::Compatibility::Version.mongoid5_or_newer?
|
740
|
-
Book.collection.insert_one(title: 'Proust and Signs')
|
741
|
-
else
|
742
|
-
Book.collection.insert(title: 'Proust and Signs')
|
743
|
-
end
|
744
|
-
Book.where(title: 'Proust and Signs').first
|
745
|
-
end
|
746
|
-
|
747
|
-
it 'should return the id if there is no slug' do
|
748
|
-
expect(book_no_slug.to_param).to eq(book_no_slug.id.to_s)
|
749
|
-
expect(book_no_slug.slugs).to be_nil
|
750
|
-
end
|
751
|
-
|
752
|
-
it 'should not persist the record' do
|
753
|
-
expect(book_no_slug.to_param).to eq(book_no_slug._id.to_s)
|
754
|
-
end
|
755
|
-
end
|
756
|
-
end
|
757
|
-
|
758
|
-
describe '#_slugs_changed?' do
|
759
|
-
before do
|
760
|
-
Book.create(title: 'A Thousand Plateaus')
|
761
|
-
end
|
762
|
-
|
763
|
-
let(:book) { Book.first }
|
764
|
-
|
765
|
-
it 'is initially unchanged' do
|
766
|
-
expect(book._slugs_changed?).to be_falsey
|
767
|
-
end
|
768
|
-
|
769
|
-
it 'tracks changes' do
|
770
|
-
book.slugs = ['Anti Oedipus']
|
771
|
-
expect(book._slugs_changed?).to be_truthy
|
772
|
-
end
|
773
|
-
end
|
774
|
-
|
775
|
-
describe 'when regular expression matches, but document does not' do
|
776
|
-
let!(:book_1) { Book.create(title: 'book-1') }
|
777
|
-
let!(:book_2) { Book.create(title: 'book') }
|
778
|
-
let!(:book_3) { Book.create(title: 'book') }
|
779
|
-
|
780
|
-
it 'book_2 should have the user supplied title without -1 after it' do
|
781
|
-
expect(book_2.to_param).to eql 'book'
|
782
|
-
end
|
783
|
-
|
784
|
-
it 'book_3 should have a generated slug' do
|
785
|
-
expect(book_3.to_param).to eql 'book-2'
|
786
|
-
end
|
787
|
-
end
|
788
|
-
|
789
|
-
context 'when the slugged field is set manually' do
|
790
|
-
context 'when it set to a non-empty string' do
|
791
|
-
it 'respects the provided slug' do
|
792
|
-
book = Book.create(title: 'A Thousand Plateaus', slugs: ['not-what-you-expected'])
|
793
|
-
expect(book.to_param).to eql 'not-what-you-expected'
|
794
|
-
end
|
795
|
-
|
796
|
-
it 'ensures uniqueness' do
|
797
|
-
book1 = Book.create(title: 'A Thousand Plateaus', slugs: ['not-what-you-expected'])
|
798
|
-
expect(book1.to_param).to eql 'not-what-you-expected'
|
799
|
-
if Mongoid::Compatibility::Version.mongoid5_or_newer?
|
800
|
-
expect do
|
801
|
-
Book.create(title: 'A Thousand Plateaus', slugs: ['not-what-you-expected'])
|
802
|
-
end.to raise_error Mongo::Error::OperationFailure, /duplicate/
|
803
|
-
elsif Mongoid::Compatibility::Version.mongoid4?
|
804
|
-
expect do
|
805
|
-
Book.create(title: 'A Thousand Plateaus', slugs: ['not-what-you-expected'])
|
806
|
-
end.to raise_error Moped::Errors::OperationFailure, /duplicate/
|
807
|
-
end
|
808
|
-
end
|
809
|
-
|
810
|
-
it 'updates the slug when a new one is passed in' do
|
811
|
-
book = Book.create(title: 'A Thousand Plateaus', slugs: ['not-what-you-expected'])
|
812
|
-
book.slugs = ['not-it-either']
|
813
|
-
book.save
|
814
|
-
expect(book.to_param).to eql 'not-it-either'
|
815
|
-
end
|
816
|
-
|
817
|
-
it 'updates the slug when a new one is appended' do
|
818
|
-
book = Book.create(title: 'A Thousand Plateaus', slugs: ['not-what-you-expected'])
|
819
|
-
book.slugs.push 'not-it-either'
|
820
|
-
book.save
|
821
|
-
expect(book.to_param).to eql 'not-it-either'
|
822
|
-
end
|
823
|
-
|
824
|
-
it 'updates the slug to a unique slug when a new one is appended' do
|
825
|
-
Book.create(title: 'Sleepyhead')
|
826
|
-
book2 = Book.create(title: 'A Thousand Plateaus')
|
827
|
-
book2.slugs.push 'sleepyhead'
|
828
|
-
if Mongoid::Compatibility::Version.mongoid5_or_newer?
|
829
|
-
expect do
|
830
|
-
book2.save
|
831
|
-
end.to raise_error Mongo::Error::OperationFailure, /duplicate/
|
832
|
-
elsif Mongoid::Compatibility::Version.mongoid4?
|
833
|
-
expect do
|
834
|
-
book2.save
|
835
|
-
end.to raise_error Moped::Errors::OperationFailure, /duplicate/
|
836
|
-
end
|
837
|
-
end
|
838
|
-
end
|
839
|
-
|
840
|
-
context 'when it is set to an empty string' do
|
841
|
-
it 'generate a new one' do
|
842
|
-
book = Book.create(title: 'A Thousand Plateaus')
|
843
|
-
expect(book.to_param).to eql 'a-thousand-plateaus'
|
844
|
-
end
|
845
|
-
end
|
846
|
-
end
|
847
|
-
|
848
|
-
context 'slug can be localized' do
|
849
|
-
before(:each) do
|
850
|
-
@old_locale = I18n.locale
|
851
|
-
end
|
852
|
-
|
853
|
-
after(:each) do
|
854
|
-
I18n.locale = @old_locale
|
855
|
-
end
|
856
|
-
|
857
|
-
it 'generates a new slug for each localization' do
|
858
|
-
page = PageSlugLocalized.new
|
859
|
-
page.title = 'Title on English'
|
860
|
-
page.save
|
861
|
-
expect(page.slug).to eql 'title-on-english'
|
862
|
-
I18n.locale = :nl
|
863
|
-
page.title = 'Title on Netherlands'
|
864
|
-
page.save
|
865
|
-
expect(page.slug).to eql 'title-on-netherlands'
|
866
|
-
end
|
867
|
-
|
868
|
-
it 'returns _id if no slug' do
|
869
|
-
page = PageSlugLocalized.new
|
870
|
-
page.title = 'Title on English'
|
871
|
-
page.save
|
872
|
-
expect(page.slug).to eql 'title-on-english'
|
873
|
-
I18n.locale = :nl
|
874
|
-
expect(page.slug).to eql page._id.to_s
|
875
|
-
end
|
876
|
-
|
877
|
-
it 'fallbacks if slug not localized yet' do
|
878
|
-
page = PageSlugLocalized.new
|
879
|
-
page.title = 'Title on English'
|
880
|
-
page.save
|
881
|
-
expect(page.slug).to eql 'title-on-english'
|
882
|
-
I18n.locale = :nl
|
883
|
-
expect(page.slug).to eql page._id.to_s
|
884
|
-
|
885
|
-
# Turn on i18n fallback
|
886
|
-
require 'i18n/backend/fallbacks'
|
887
|
-
I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks)
|
888
|
-
::I18n.fallbacks[:nl] = %i[nl en]
|
889
|
-
expect(page.slug).to eql 'title-on-english'
|
890
|
-
fallback_slug = page.slug
|
891
|
-
|
892
|
-
fallback_page = begin
|
893
|
-
PageSlugLocalized.find(fallback_slug)
|
894
|
-
rescue StandardError
|
895
|
-
nil
|
896
|
-
end
|
897
|
-
expect(fallback_page).to eq(page)
|
898
|
-
|
899
|
-
# Restore fallback for next tests
|
900
|
-
::I18n.fallbacks[:nl] = [:nl]
|
901
|
-
end
|
902
|
-
|
903
|
-
it 'returns a default slug if not localized' do
|
904
|
-
page = PageLocalize.new
|
905
|
-
page.title = 'Title on English'
|
906
|
-
page.save
|
907
|
-
expect(page.slug).to eql 'title-on-english'
|
908
|
-
I18n.locale = :nl
|
909
|
-
page.title = 'Title on Netherlands'
|
910
|
-
expect(page.slug).to eql 'title-on-english'
|
911
|
-
page.save
|
912
|
-
expect(page.slug).to eql 'title-on-netherlands'
|
913
|
-
end
|
914
|
-
|
915
|
-
it 'slugs properly when translations are set directly' do
|
916
|
-
page = PageSlugLocalized.new
|
917
|
-
page.title_translations = { 'en' => 'Title on English', 'nl' => 'Title on Netherlands' }
|
918
|
-
page.save
|
919
|
-
expect(page._slugs_translations).to eq('en' => ['title-on-english'], 'nl' => ['title-on-netherlands'])
|
920
|
-
end
|
921
|
-
|
922
|
-
it 'exact same title multiple langauges' do
|
923
|
-
page = PageSlugLocalized.new
|
924
|
-
page.title_translations = { 'en' => 'Title on English', 'nl' => 'Title on English' }
|
925
|
-
page.save
|
926
|
-
expect(page._slugs_translations).to eq('en' => ['title-on-english'], 'nl' => ['title-on-english'])
|
927
|
-
|
928
|
-
page = PageSlugLocalized.create(title_translations: { 'en' => 'Title on English2', 'nl' => 'Title on English2' })
|
929
|
-
expect(page._slugs_translations).to eq('en' => ['title-on-english2'], 'nl' => ['title-on-english2'])
|
930
|
-
end
|
931
|
-
|
932
|
-
it 'does not produce duplicate slugs' do
|
933
|
-
old_locale = I18n.locale
|
934
|
-
|
935
|
-
# Using a default locale of en.
|
936
|
-
page = PageSlugLocalized.new
|
937
|
-
page.title = 'Title on English'
|
938
|
-
page.save
|
939
|
-
I18n.locale = 'nl'
|
940
|
-
page.title = 'Title on Netherlands'
|
941
|
-
page.save
|
942
|
-
expect(page.title_translations).to eq('en' => 'Title on English', 'nl' => 'Title on Netherlands')
|
943
|
-
|
944
|
-
I18n.locale = old_locale
|
945
|
-
page.title = 'Title on English'
|
946
|
-
expect(page.title_translations).to eq('en' => 'Title on English', 'nl' => 'Title on Netherlands')
|
947
|
-
expect(page._slugs_translations).to eq('en' => ['title-on-english'], 'nl' => ['title-on-netherlands'])
|
948
|
-
end
|
949
|
-
|
950
|
-
it 'does not produce duplicate slugs when one has changed' do
|
951
|
-
old_locale = I18n.locale
|
952
|
-
|
953
|
-
# Using a default locale of en.
|
954
|
-
page = PageSlugLocalized.new
|
955
|
-
page.title = 'Title on English'
|
956
|
-
page.save
|
957
|
-
I18n.locale = 'nl'
|
958
|
-
page.title = 'Title on Netherlands'
|
959
|
-
page.save
|
960
|
-
expect(page.title_translations).to eq('en' => 'Title on English', 'nl' => 'Title on Netherlands')
|
961
|
-
|
962
|
-
I18n.locale = old_locale
|
963
|
-
page.title = 'Modified Title on English'
|
964
|
-
page.save
|
965
|
-
expect(page.title_translations).to eq('en' => 'Modified Title on English',
|
966
|
-
'nl' => 'Title on Netherlands')
|
967
|
-
expect(page._slugs_translations).to eq('en' => ['modified-title-on-english'],
|
968
|
-
'nl' => ['title-on-netherlands'])
|
969
|
-
end
|
970
|
-
|
971
|
-
it 'does not produce duplicate slugs when transactions are set directly' do
|
972
|
-
page = PageSlugLocalized.new
|
973
|
-
page.title_translations = { 'en' => 'Title on English', 'nl' => 'Title on Netherlands' }
|
974
|
-
page.save
|
975
|
-
page.title_translations = { 'en' => 'Title on English', 'nl' => 'Title on Netherlands' }
|
976
|
-
page.save
|
977
|
-
expect(page._slugs_translations).to eq('en' => ['title-on-english'], 'nl' => ['title-on-netherlands'])
|
978
|
-
end
|
979
|
-
|
980
|
-
it 'does not produce duplicate slugs when transactions are set directly and one has changed' do
|
981
|
-
page = PageSlugLocalized.new
|
982
|
-
page.title_translations = { 'en' => 'Title on English', 'nl' => 'Title on Netherlands' }
|
983
|
-
page.save
|
984
|
-
page.title_translations = { 'en' => 'Modified Title on English',
|
985
|
-
'nl' => 'Title on Netherlands' }
|
986
|
-
page.save
|
987
|
-
expect(page._slugs_translations).to eq('en' => ['modified-title-on-english'],
|
988
|
-
'nl' => ['title-on-netherlands'])
|
989
|
-
end
|
990
|
-
|
991
|
-
it 'works with a custom slug strategy' do
|
992
|
-
page = PageSlugLocalizedCustom.new
|
993
|
-
page.title = 'a title for the slug'
|
994
|
-
page.save
|
995
|
-
expect(page._slugs_translations).to eq('en' => ['a-title-for-the-slug'], 'nl' => ['a-title-for-the-slug'])
|
996
|
-
end
|
997
|
-
end
|
998
|
-
|
999
|
-
context 'slug can be localized when using history' do
|
1000
|
-
before(:each) do
|
1001
|
-
@old_locale = I18n.locale
|
1002
|
-
end
|
1003
|
-
|
1004
|
-
after(:each) do
|
1005
|
-
I18n.locale = @old_locale
|
1006
|
-
end
|
1007
|
-
|
1008
|
-
it 'generate a new slug for each localization and keep history' do
|
1009
|
-
old_locale = I18n.locale
|
1010
|
-
|
1011
|
-
page = PageSlugLocalizedHistory.new
|
1012
|
-
page.title = 'Title on English'
|
1013
|
-
page.save
|
1014
|
-
expect(page.slug).to eql 'title-on-english'
|
1015
|
-
I18n.locale = :nl
|
1016
|
-
page.title = 'Title on Netherlands'
|
1017
|
-
page.save
|
1018
|
-
expect(page.slug).to eql 'title-on-netherlands'
|
1019
|
-
I18n.locale = old_locale
|
1020
|
-
page.title = 'Modified title on English'
|
1021
|
-
page.save
|
1022
|
-
expect(page.slug).to eql 'modified-title-on-english'
|
1023
|
-
expect(page.slug).to include('title-on-english')
|
1024
|
-
I18n.locale = :nl
|
1025
|
-
page.title = 'Modified title on Netherlands'
|
1026
|
-
page.save
|
1027
|
-
expect(page.slug).to eql 'modified-title-on-netherlands'
|
1028
|
-
expect(page.slug).to include('title-on-netherlands')
|
1029
|
-
end
|
1030
|
-
|
1031
|
-
it 'returns _id if no slug' do
|
1032
|
-
page = PageSlugLocalizedHistory.new
|
1033
|
-
page.title = 'Title on English'
|
1034
|
-
page.save
|
1035
|
-
expect(page.slug).to eql 'title-on-english'
|
1036
|
-
I18n.locale = :nl
|
1037
|
-
expect(page.slug).to eql page._id.to_s
|
1038
|
-
end
|
1039
|
-
|
1040
|
-
it 'fallbacks if slug not localized yet' do
|
1041
|
-
page = PageSlugLocalizedHistory.new
|
1042
|
-
page.title = 'Title on English'
|
1043
|
-
page.save
|
1044
|
-
expect(page.slug).to eql 'title-on-english'
|
1045
|
-
I18n.locale = :nl
|
1046
|
-
expect(page.slug).to eql page._id.to_s
|
1047
|
-
|
1048
|
-
# Turn on i18n fallback
|
1049
|
-
require 'i18n/backend/fallbacks'
|
1050
|
-
I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks)
|
1051
|
-
::I18n.fallbacks[:nl] = %i[nl en]
|
1052
|
-
expect(page.slug).to eql 'title-on-english'
|
1053
|
-
fallback_slug = page.slug
|
1054
|
-
|
1055
|
-
fallback_page = begin
|
1056
|
-
PageSlugLocalizedHistory.find(fallback_slug)
|
1057
|
-
rescue StandardError
|
1058
|
-
nil
|
1059
|
-
end
|
1060
|
-
expect(fallback_page).to eq(page)
|
1061
|
-
end
|
1062
|
-
|
1063
|
-
it 'slugs properly when translations are set directly' do
|
1064
|
-
page = PageSlugLocalizedHistory.new
|
1065
|
-
page.title_translations = { 'en' => 'Title on English', 'nl' => 'Title on Netherlands' }
|
1066
|
-
page.save
|
1067
|
-
page.title_translations = { 'en' => 'Modified Title on English',
|
1068
|
-
'nl' => 'Modified Title on Netherlands' }
|
1069
|
-
page.save
|
1070
|
-
expect(page._slugs_translations).to eq('en' => ['title-on-english', 'modified-title-on-english'],
|
1071
|
-
'nl' => ['title-on-netherlands', 'modified-title-on-netherlands'])
|
1072
|
-
end
|
1073
|
-
|
1074
|
-
it 'does not produce duplicate slugs' do
|
1075
|
-
old_locale = I18n.locale
|
1076
|
-
|
1077
|
-
# Using a default locale of en.
|
1078
|
-
page = PageSlugLocalizedHistory.new
|
1079
|
-
page.title = 'Title on English'
|
1080
|
-
page.save
|
1081
|
-
I18n.locale = 'nl'
|
1082
|
-
page.title = 'Title on Netherlands'
|
1083
|
-
page.save
|
1084
|
-
expect(page.title_translations).to eq('en' => 'Title on English', 'nl' => 'Title on Netherlands')
|
1085
|
-
|
1086
|
-
I18n.locale = old_locale
|
1087
|
-
page.title = 'Title on English'
|
1088
|
-
expect(page.title_translations).to eq('en' => 'Title on English', 'nl' => 'Title on Netherlands')
|
1089
|
-
expect(page._slugs_translations).to eq('en' => ['title-on-english'], 'nl' => ['title-on-netherlands'])
|
1090
|
-
end
|
1091
|
-
|
1092
|
-
it 'does not produce duplicate slugs when one has changed' do
|
1093
|
-
old_locale = I18n.locale
|
1094
|
-
|
1095
|
-
# Using a default locale of en.
|
1096
|
-
page = PageSlugLocalizedHistory.new
|
1097
|
-
page.title = 'Title on English'
|
1098
|
-
page.save
|
1099
|
-
I18n.locale = 'nl'
|
1100
|
-
page.title = 'Title on Netherlands'
|
1101
|
-
page.save
|
1102
|
-
expect(page.title_translations).to eq('en' => 'Title on English', 'nl' => 'Title on Netherlands')
|
1103
|
-
|
1104
|
-
I18n.locale = old_locale
|
1105
|
-
page.title = 'Modified Title on English'
|
1106
|
-
page.save
|
1107
|
-
expect(page.title_translations).to eq('en' => 'Modified Title on English',
|
1108
|
-
'nl' => 'Title on Netherlands')
|
1109
|
-
expect(page._slugs_translations).to eq('en' => ['title-on-english', 'modified-title-on-english'],
|
1110
|
-
'nl' => ['title-on-netherlands'])
|
1111
|
-
end
|
1112
|
-
|
1113
|
-
it 'does not produce duplicate slugs when transactions are set directly' do
|
1114
|
-
page = PageSlugLocalizedHistory.new
|
1115
|
-
page.title_translations = { 'en' => 'Title on English', 'nl' => 'Title on Netherlands' }
|
1116
|
-
page.save
|
1117
|
-
page.title_translations = { 'en' => 'Title on English', 'nl' => 'Title on Netherlands' }
|
1118
|
-
page.save
|
1119
|
-
expect(page._slugs_translations).to eq('en' => ['title-on-english'], 'nl' => ['title-on-netherlands'])
|
1120
|
-
end
|
1121
|
-
|
1122
|
-
it 'does not produce duplicate slugs when transactions are set directly and one has changed' do
|
1123
|
-
page = PageSlugLocalizedHistory.new
|
1124
|
-
page.title_translations = { 'en' => 'Title on English', 'nl' => 'Title on Netherlands' }
|
1125
|
-
page.save
|
1126
|
-
page.title_translations = { 'en' => 'Modified Title on English', 'nl' => 'Title on Netherlands' }
|
1127
|
-
page.save
|
1128
|
-
expect(page._slugs_translations).to eq('en' => ['title-on-english', 'modified-title-on-english'],
|
1129
|
-
'nl' => ['title-on-netherlands'])
|
1130
|
-
end
|
1131
|
-
end
|
1132
|
-
|
1133
|
-
describe 'slug_max_length' do
|
1134
|
-
before do
|
1135
|
-
Author.create_indexes
|
1136
|
-
end
|
1137
|
-
|
1138
|
-
after do
|
1139
|
-
Author.remove_indexes
|
1140
|
-
end
|
1141
|
-
|
1142
|
-
it 'can be assigned to nil' do
|
1143
|
-
expect(Book.slug_max_length).to be nil
|
1144
|
-
end
|
1145
|
-
|
1146
|
-
it 'defaults to MONGO_INDEX_KEY_LIMIT_BYTES - 32' do
|
1147
|
-
expect(Article.slug_max_length).to eq Mongoid::Slug::MONGO_INDEX_KEY_LIMIT_BYTES - 32
|
1148
|
-
end
|
1149
|
-
|
1150
|
-
it 'is assigned via max_length' do
|
1151
|
-
expect(Author.slug_max_length).to eq 256
|
1152
|
-
end
|
1153
|
-
|
1154
|
-
it 'enforces max length of slug' do
|
1155
|
-
author1 = Author.create!(last_name: 't' * 1024)
|
1156
|
-
expect(author1.slug.length).to eq 256
|
1157
|
-
expect(author1.slug.ends_with?('ttt')).to be true
|
1158
|
-
author2 = Author.create!(last_name: 't' * 1024)
|
1159
|
-
expect(author2.slug.length).to eq 258
|
1160
|
-
expect(author2.slug.ends_with?('tt-1')).to be true
|
1161
|
-
author3 = Author.create!(last_name: 't' * 1024)
|
1162
|
-
expect(author3.slug.length).to eq 258
|
1163
|
-
expect(author3.slug.ends_with?('tt-2')).to be true
|
1164
|
-
end
|
1165
|
-
end
|
1166
|
-
|
1167
|
-
context 'has_many / belongs_to' do
|
1168
|
-
let(:book) { Book.create!(title: 'War and Peace') }
|
1169
|
-
it 'allows for duplicates with different slugs' do
|
1170
|
-
Author.create!(first_name: 'Leo', last_name: 'Tostoy')
|
1171
|
-
expect { book.authors.create!(first_name: 'Leo', last_name: 'Tostoy') }.to_not raise_error
|
1172
|
-
end
|
1173
|
-
end
|
1174
|
-
end
|
1175
|
-
end
|