friendly_id 5.2.4 → 5.5.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 +5 -5
- checksums.yaml.gz.sig +0 -0
- data/.github/FUNDING.yml +1 -0
- data/.github/dependabot.yml +6 -0
- data/.github/stale.yml +17 -0
- data/.github/workflows/test.yml +58 -0
- data/Changelog.md +41 -0
- data/Gemfile +10 -11
- data/README.md +42 -15
- data/Rakefile +24 -27
- data/bench.rb +30 -27
- data/certs/parndt.pem +27 -0
- data/friendly_id.gemspec +28 -27
- data/gemfiles/Gemfile.rails-5.2.rb +11 -16
- data/gemfiles/Gemfile.rails-6.0.rb +22 -0
- data/gemfiles/Gemfile.rails-6.1.rb +22 -0
- data/gemfiles/Gemfile.rails-7.0.rb +22 -0
- data/guide.rb +5 -5
- data/lib/friendly_id/base.rb +61 -68
- data/lib/friendly_id/candidates.rb +9 -11
- data/lib/friendly_id/configuration.rb +8 -8
- data/lib/friendly_id/finder_methods.rb +72 -13
- data/lib/friendly_id/finders.rb +64 -67
- data/lib/friendly_id/history.rb +72 -66
- data/lib/friendly_id/initializer.rb +5 -5
- data/lib/friendly_id/migration.rb +10 -11
- data/lib/friendly_id/object_utils.rb +2 -2
- data/lib/friendly_id/reserved.rb +28 -32
- data/lib/friendly_id/scoped.rb +105 -103
- data/lib/friendly_id/sequentially_slugged/calculator.rb +69 -0
- data/lib/friendly_id/sequentially_slugged.rb +21 -58
- data/lib/friendly_id/simple_i18n.rb +75 -69
- data/lib/friendly_id/slug.rb +1 -2
- data/lib/friendly_id/slug_generator.rb +1 -3
- data/lib/friendly_id/slugged.rb +236 -239
- data/lib/friendly_id/version.rb +1 -1
- data/lib/friendly_id.rb +41 -45
- data/lib/generators/friendly_id_generator.rb +9 -9
- data/test/base_test.rb +10 -13
- data/test/benchmarks/finders.rb +28 -26
- data/test/benchmarks/object_utils.rb +13 -13
- data/test/candidates_test.rb +17 -18
- data/test/configuration_test.rb +7 -11
- data/test/core_test.rb +1 -2
- data/test/databases.yml +7 -4
- data/test/finders_test.rb +52 -5
- data/test/generator_test.rb +16 -26
- data/test/helper.rb +33 -20
- data/test/history_test.rb +116 -72
- data/test/numeric_slug_test.rb +31 -0
- data/test/object_utils_test.rb +0 -2
- data/test/reserved_test.rb +9 -11
- data/test/schema.rb +5 -4
- data/test/scoped_test.rb +26 -15
- data/test/sequentially_slugged_test.rb +107 -33
- data/test/shared.rb +17 -18
- data/test/simple_i18n_test.rb +23 -13
- data/test/slugged_test.rb +254 -78
- data/test/sti_test.rb +19 -21
- data.tar.gz.sig +0 -0
- metadata +49 -19
- metadata.gz.sig +1 -0
- data/.travis.yml +0 -57
- data/gemfiles/Gemfile.rails-4.0.rb +0 -30
- data/gemfiles/Gemfile.rails-4.1.rb +0 -29
- data/gemfiles/Gemfile.rails-4.2.rb +0 -28
- data/gemfiles/Gemfile.rails-5.0.rb +0 -28
- data/gemfiles/Gemfile.rails-5.1.rb +0 -27
data/test/slugged_test.rb
CHANGED
@@ -2,25 +2,24 @@ require "helper"
|
|
2
2
|
|
3
3
|
class Journalist < ActiveRecord::Base
|
4
4
|
extend FriendlyId
|
5
|
-
friendly_id :name, :
|
5
|
+
friendly_id :name, use: :slugged
|
6
6
|
end
|
7
7
|
|
8
8
|
class Article < ActiveRecord::Base
|
9
9
|
extend FriendlyId
|
10
|
-
friendly_id :name, :
|
10
|
+
friendly_id :name, use: :slugged
|
11
11
|
end
|
12
12
|
|
13
13
|
class Novelist < ActiveRecord::Base
|
14
14
|
extend FriendlyId
|
15
|
-
friendly_id :name, :
|
15
|
+
friendly_id :name, use: :slugged, sequence_separator: "_"
|
16
16
|
|
17
17
|
def normalize_friendly_id(string)
|
18
|
-
super.
|
18
|
+
super.tr("-", "_")
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
22
|
class SluggedTest < TestCaseClass
|
23
|
-
|
24
23
|
include FriendlyId::Test
|
25
24
|
include FriendlyId::Test::Shared::Core
|
26
25
|
include FriendlyId::Test::Shared::Slugged
|
@@ -33,13 +32,13 @@ class SluggedTest < TestCaseClass
|
|
33
32
|
model_class = Class.new(ActiveRecord::Base) do
|
34
33
|
self.table_name = "articles"
|
35
34
|
extend FriendlyId
|
36
|
-
friendly_id :name, :
|
37
|
-
validates_length_of :slug, :
|
35
|
+
friendly_id :name, use: :slugged
|
36
|
+
validates_length_of :slug, maximum: 1
|
38
37
|
def self.name
|
39
38
|
"Article"
|
40
39
|
end
|
41
40
|
end
|
42
|
-
instance = model_class.new :
|
41
|
+
instance = model_class.new name: "hello"
|
43
42
|
refute instance.valid?
|
44
43
|
end
|
45
44
|
|
@@ -55,21 +54,21 @@ class SluggedTest < TestCaseClass
|
|
55
54
|
model_class = Class.new(ActiveRecord::Base) do
|
56
55
|
self.table_name = "journalists"
|
57
56
|
extend FriendlyId
|
58
|
-
friendly_id :name, :
|
57
|
+
friendly_id :name, use: :slugged
|
59
58
|
validates_uniqueness_of :slug_en
|
60
59
|
def self.name
|
61
60
|
"Journalist"
|
62
61
|
end
|
63
62
|
end
|
64
63
|
transaction do
|
65
|
-
instance = model_class.create! :
|
66
|
-
instance2 = model_class.create :
|
64
|
+
instance = model_class.create! name: "hello", slug_en: "hello"
|
65
|
+
instance2 = model_class.create name: "hello", slug_en: "hello"
|
67
66
|
assert instance.valid?
|
68
67
|
refute instance2.valid?
|
69
68
|
end
|
70
69
|
end
|
71
70
|
|
72
|
-
test
|
71
|
+
test "should allow a record to reuse its own slug" do
|
73
72
|
with_instance_of(model_class) do |record|
|
74
73
|
old_id = record.friendly_id
|
75
74
|
record.slug = nil
|
@@ -92,10 +91,29 @@ class SluggedTest < TestCaseClass
|
|
92
91
|
end
|
93
92
|
end
|
94
93
|
|
95
|
-
test "should
|
94
|
+
test "should set slug on create if unrelated validations fail" do
|
95
|
+
klass = Class.new model_class do
|
96
|
+
validates_presence_of :active
|
97
|
+
friendly_id :name, use: :slugged
|
98
|
+
|
99
|
+
def self.name
|
100
|
+
"Journalist"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
transaction do
|
105
|
+
instance = klass.new name: "foo"
|
106
|
+
refute instance.save
|
107
|
+
refute instance.valid?
|
108
|
+
assert_equal "foo", instance.slug
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
test "should not set slug on create if slug validation fails" do
|
96
113
|
klass = Class.new model_class do
|
97
114
|
validates_presence_of :active
|
98
|
-
|
115
|
+
validates_length_of :slug, minimum: 2
|
116
|
+
friendly_id :name, use: :slugged
|
99
117
|
|
100
118
|
def self.name
|
101
119
|
"Journalist"
|
@@ -103,19 +121,39 @@ class SluggedTest < TestCaseClass
|
|
103
121
|
end
|
104
122
|
|
105
123
|
transaction do
|
106
|
-
instance = klass.new :
|
124
|
+
instance = klass.new name: "x"
|
107
125
|
refute instance.save
|
108
126
|
refute instance.valid?
|
109
127
|
assert_nil instance.slug
|
110
128
|
end
|
111
129
|
end
|
112
130
|
|
113
|
-
test "should
|
131
|
+
test "should set slug on create if unrelated validations fail with custom slug_column" do
|
114
132
|
klass = Class.new(ActiveRecord::Base) do
|
115
|
-
self.table_name =
|
133
|
+
self.table_name = "authors"
|
116
134
|
extend FriendlyId
|
117
135
|
validates_presence_of :active
|
118
|
-
friendly_id :name, :
|
136
|
+
friendly_id :name, use: :slugged, slug_column: :subdomain
|
137
|
+
|
138
|
+
def self.name
|
139
|
+
"Author"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
transaction do
|
144
|
+
instance = klass.new name: "foo"
|
145
|
+
refute instance.save
|
146
|
+
refute instance.valid?
|
147
|
+
assert_equal "foo", instance.subdomain
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
test "should not set slug on create if custom slug column validations fail" do
|
152
|
+
klass = Class.new(ActiveRecord::Base) do
|
153
|
+
self.table_name = "authors"
|
154
|
+
extend FriendlyId
|
155
|
+
validates_length_of :subdomain, minimum: 2
|
156
|
+
friendly_id :name, use: :slugged, slug_column: :subdomain
|
119
157
|
|
120
158
|
def self.name
|
121
159
|
"Author"
|
@@ -123,17 +161,17 @@ class SluggedTest < TestCaseClass
|
|
123
161
|
end
|
124
162
|
|
125
163
|
transaction do
|
126
|
-
instance = klass.new :
|
164
|
+
instance = klass.new name: "x"
|
127
165
|
refute instance.save
|
128
166
|
refute instance.valid?
|
129
167
|
assert_nil instance.subdomain
|
130
168
|
end
|
131
169
|
end
|
132
170
|
|
133
|
-
test "should
|
171
|
+
test "should keep new slug on save if unrelated validations fail" do
|
134
172
|
klass = Class.new model_class do
|
135
173
|
validates_presence_of :active
|
136
|
-
friendly_id :name, :
|
174
|
+
friendly_id :name, use: :slugged
|
137
175
|
|
138
176
|
def self.name
|
139
177
|
"Journalist"
|
@@ -141,22 +179,42 @@ class SluggedTest < TestCaseClass
|
|
141
179
|
end
|
142
180
|
|
143
181
|
transaction do
|
144
|
-
instance = klass.new :
|
182
|
+
instance = klass.new name: "foo", active: true
|
145
183
|
assert instance.save
|
146
184
|
assert instance.valid?
|
147
|
-
instance.name =
|
185
|
+
instance.name = "foobar"
|
148
186
|
instance.slug = nil
|
149
187
|
instance.active = nil
|
150
188
|
refute instance.save
|
151
189
|
refute instance.valid?
|
152
|
-
assert_equal
|
190
|
+
assert_equal "foobar", instance.slug
|
153
191
|
end
|
154
192
|
end
|
155
193
|
|
194
|
+
test "should not update slug on save if slug validations fail" do
|
195
|
+
klass = Class.new model_class do
|
196
|
+
validates_length_of :slug, minimum: 2
|
197
|
+
friendly_id :name, use: :slugged
|
198
|
+
|
199
|
+
def self.name
|
200
|
+
"Journalist"
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
transaction do
|
205
|
+
instance = klass.new name: "foo", active: true
|
206
|
+
assert instance.save
|
207
|
+
assert instance.valid?
|
208
|
+
instance.name = "x"
|
209
|
+
instance.slug = nil
|
210
|
+
instance.active = nil
|
211
|
+
refute instance.save
|
212
|
+
assert_equal "foo", instance.slug
|
213
|
+
end
|
214
|
+
end
|
156
215
|
end
|
157
216
|
|
158
217
|
class SlugGeneratorTest < TestCaseClass
|
159
|
-
|
160
218
|
include FriendlyId::Test
|
161
219
|
|
162
220
|
def model_class
|
@@ -172,11 +230,11 @@ class SlugGeneratorTest < TestCaseClass
|
|
172
230
|
# self.abstract_class = true
|
173
231
|
self.table_name = "journalists"
|
174
232
|
extend FriendlyId
|
175
|
-
friendly_id :name, :
|
233
|
+
friendly_id :name, use: :slugged, slug_column: "strange name"
|
176
234
|
end
|
177
235
|
|
178
236
|
begin
|
179
|
-
with_instance_of(model_class) {|record| assert model_class.friendly.find(record.friendly_id)}
|
237
|
+
with_instance_of(model_class) { |record| assert model_class.friendly.find(record.friendly_id) }
|
180
238
|
rescue ActiveRecord::StatementInvalid
|
181
239
|
flunk "column name was not quoted"
|
182
240
|
end
|
@@ -184,9 +242,9 @@ class SlugGeneratorTest < TestCaseClass
|
|
184
242
|
|
185
243
|
test "should not resequence lower sequences on update" do
|
186
244
|
transaction do
|
187
|
-
m1 = model_class.create! :
|
245
|
+
m1 = model_class.create! name: "a b c d"
|
188
246
|
assert_equal "a-b-c-d", m1.slug
|
189
|
-
model_class.create! :
|
247
|
+
model_class.create! name: "a b c d"
|
190
248
|
m1 = model_class.friendly.find(m1.id)
|
191
249
|
m1.save!
|
192
250
|
assert_equal "a-b-c-d", m1.slug
|
@@ -195,37 +253,35 @@ class SlugGeneratorTest < TestCaseClass
|
|
195
253
|
|
196
254
|
test "should correctly sequence slugs that end with numbers" do
|
197
255
|
transaction do
|
198
|
-
record1 = model_class.create! :
|
256
|
+
record1 = model_class.create! name: "Peugeot 206"
|
199
257
|
assert_equal "peugeot-206", record1.slug
|
200
|
-
record2 = model_class.create! :
|
201
|
-
assert_match(/\Apeugeot-206-([a-z0-9]
|
258
|
+
record2 = model_class.create! name: "Peugeot 206"
|
259
|
+
assert_match(/\Apeugeot-206-([a-z0-9]+-){4}[a-z0-9]+\z/, record2.slug)
|
202
260
|
end
|
203
261
|
end
|
204
262
|
|
205
263
|
test "should correctly sequence slugs with underscores" do
|
206
264
|
transaction do
|
207
|
-
Novelist.create! :
|
208
|
-
record2 = Novelist.create! :
|
209
|
-
assert_equal
|
265
|
+
Novelist.create! name: "wordsfail, buildings tumble"
|
266
|
+
record2 = Novelist.create! name: "word fail"
|
267
|
+
assert_equal "word_fail", record2.slug
|
210
268
|
end
|
211
269
|
end
|
212
270
|
|
213
271
|
test "should correctly sequence numeric slugs" do
|
214
272
|
transaction do
|
215
|
-
n2 = 2.times.map {Article.create :
|
273
|
+
n2 = 2.times.map { Article.create name: "123" }.last
|
216
274
|
assert_match(/\A123-.*/, n2.friendly_id)
|
217
275
|
end
|
218
276
|
end
|
219
|
-
|
220
277
|
end
|
221
278
|
|
222
279
|
class SlugSeparatorTest < TestCaseClass
|
223
|
-
|
224
280
|
include FriendlyId::Test
|
225
281
|
|
226
282
|
class Journalist < ActiveRecord::Base
|
227
283
|
extend FriendlyId
|
228
|
-
friendly_id :name, :
|
284
|
+
friendly_id :name, use: :slugged, sequence_separator: ":"
|
229
285
|
end
|
230
286
|
|
231
287
|
def model_class
|
@@ -234,7 +290,7 @@ class SlugSeparatorTest < TestCaseClass
|
|
234
290
|
|
235
291
|
test "should sequence with configured sequence separator" do
|
236
292
|
with_instance_of model_class do |record|
|
237
|
-
record2 = model_class.create! :
|
293
|
+
record2 = model_class.create! name: record.name
|
238
294
|
assert record2.friendly_id.match(/:.*\z/)
|
239
295
|
end
|
240
296
|
end
|
@@ -250,34 +306,32 @@ class SlugSeparatorTest < TestCaseClass
|
|
250
306
|
model_class = Class.new(ActiveRecord::Base) do
|
251
307
|
self.table_name = "journalists"
|
252
308
|
extend FriendlyId
|
253
|
-
friendly_id :name, :
|
309
|
+
friendly_id :name, use: :slugged, sequence_separator: "-"
|
254
310
|
def self.name
|
255
311
|
"Journalist"
|
256
312
|
end
|
257
313
|
end
|
258
314
|
transaction do
|
259
|
-
record1 = model_class.create! :
|
315
|
+
record1 = model_class.create! name: "Peugeot 206"
|
260
316
|
assert_equal "peugeot-206", record1.slug
|
261
|
-
record2 = model_class.create! :
|
262
|
-
assert_match(/\Apeugeot-206-([a-z0-9]
|
317
|
+
record2 = model_class.create! name: "Peugeot 206"
|
318
|
+
assert_match(/\Apeugeot-206-([a-z0-9]+-){4}[a-z0-9]+\z/, record2.slug)
|
263
319
|
end
|
264
320
|
end
|
265
321
|
|
266
322
|
test "should sequence blank slugs without a separator" do
|
267
|
-
with_instance_of model_class, :
|
268
|
-
assert_match(/\A([a-z0-9]
|
323
|
+
with_instance_of model_class, name: "" do |record|
|
324
|
+
assert_match(/\A([a-z0-9]+-){4}[a-z0-9]+\z/, record.slug)
|
269
325
|
end
|
270
326
|
end
|
271
|
-
|
272
327
|
end
|
273
328
|
|
274
329
|
class SlugLimitTest < TestCaseClass
|
275
|
-
|
276
330
|
include FriendlyId::Test
|
277
331
|
|
278
332
|
class Journalist < ActiveRecord::Base
|
279
333
|
extend FriendlyId
|
280
|
-
friendly_id :name, :
|
334
|
+
friendly_id :name, use: :slugged, slug_limit: 40
|
281
335
|
end
|
282
336
|
|
283
337
|
def model_class
|
@@ -286,48 +340,45 @@ class SlugLimitTest < TestCaseClass
|
|
286
340
|
|
287
341
|
test "should limit slug size" do
|
288
342
|
transaction do
|
289
|
-
m1 = model_class.create! :
|
290
|
-
assert_equal m1.slug,
|
291
|
-
m2 = model_class.create! :
|
343
|
+
m1 = model_class.create! name: "a" * 50
|
344
|
+
assert_equal m1.slug, "a" * 40
|
345
|
+
m2 = model_class.create! name: m1.name
|
292
346
|
m2.save!
|
293
347
|
# "aaa-<uid>"
|
294
|
-
assert_match(/\Aa{3}
|
348
|
+
assert_match(/\Aa{3}-/, m2.slug)
|
295
349
|
end
|
296
350
|
end
|
297
351
|
end
|
298
352
|
|
299
353
|
class DefaultScopeTest < TestCaseClass
|
300
|
-
|
301
354
|
include FriendlyId::Test
|
302
355
|
|
303
356
|
class Journalist < ActiveRecord::Base
|
304
357
|
extend FriendlyId
|
305
|
-
friendly_id :name, :
|
306
|
-
default_scope -> { where(:
|
358
|
+
friendly_id :name, use: :slugged
|
359
|
+
default_scope -> { where(active: true).order("id ASC") }
|
307
360
|
end
|
308
361
|
|
309
362
|
test "friendly_id should correctly sequence a default_scoped ordered table" do
|
310
363
|
transaction do
|
311
|
-
3.times { assert Journalist.create :
|
364
|
+
3.times { assert Journalist.create name: "a", active: true }
|
312
365
|
end
|
313
366
|
end
|
314
367
|
|
315
368
|
test "friendly_id should correctly sequence a default_scoped scoped table" do
|
316
369
|
transaction do
|
317
|
-
assert Journalist.create :
|
318
|
-
assert Journalist.create :
|
370
|
+
assert Journalist.create name: "a", active: false
|
371
|
+
assert Journalist.create name: "a", active: true
|
319
372
|
end
|
320
373
|
end
|
321
|
-
|
322
374
|
end
|
323
375
|
|
324
376
|
class UuidAsPrimaryKeyFindTest < TestCaseClass
|
325
|
-
|
326
377
|
include FriendlyId::Test
|
327
378
|
|
328
379
|
class MenuItem < ActiveRecord::Base
|
329
380
|
extend FriendlyId
|
330
|
-
friendly_id :name, :
|
381
|
+
friendly_id :name, use: :slugged
|
331
382
|
before_create :init_primary_key
|
332
383
|
|
333
384
|
def self.primary_key
|
@@ -340,6 +391,7 @@ class UuidAsPrimaryKeyFindTest < TestCaseClass
|
|
340
391
|
end
|
341
392
|
|
342
393
|
private
|
394
|
+
|
343
395
|
def init_primary_key
|
344
396
|
self.uuid_key = SecureRandom.uuid
|
345
397
|
end
|
@@ -367,46 +419,40 @@ class UuidAsPrimaryKeyFindTest < TestCaseClass
|
|
367
419
|
end
|
368
420
|
end
|
369
421
|
end
|
370
|
-
|
371
422
|
end
|
372
423
|
|
373
424
|
class UnderscoreAsSequenceSeparatorRegressionTest < TestCaseClass
|
374
|
-
|
375
425
|
include FriendlyId::Test
|
376
426
|
|
377
427
|
class Manual < ActiveRecord::Base
|
378
428
|
extend FriendlyId
|
379
|
-
friendly_id :name, :
|
429
|
+
friendly_id :name, use: :slugged, sequence_separator: "_"
|
380
430
|
end
|
381
431
|
|
382
432
|
test "should not create duplicate slugs" do
|
383
433
|
3.times do
|
384
434
|
transaction do
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
flunk "Tried to insert duplicate slug"
|
389
|
-
end
|
435
|
+
assert Manual.create! name: "foo"
|
436
|
+
rescue
|
437
|
+
flunk "Tried to insert duplicate slug"
|
390
438
|
end
|
391
439
|
end
|
392
440
|
end
|
393
|
-
|
394
441
|
end
|
395
442
|
|
396
443
|
# https://github.com/norman/friendly_id/issues/148
|
397
444
|
class FailedValidationAfterUpdateRegressionTest < TestCaseClass
|
398
|
-
|
399
445
|
include FriendlyId::Test
|
400
446
|
|
401
447
|
class Journalist < ActiveRecord::Base
|
402
448
|
extend FriendlyId
|
403
|
-
friendly_id :name, :
|
449
|
+
friendly_id :name, use: :slugged
|
404
450
|
validates_presence_of :slug_de
|
405
451
|
end
|
406
452
|
|
407
453
|
test "to_param should return the unchanged value if the slug changes before validation fails" do
|
408
454
|
transaction do
|
409
|
-
journalist = Journalist.create! :
|
455
|
+
journalist = Journalist.create! name: "Joseph Pulitzer", slug_de: "value"
|
410
456
|
assert_equal "joseph-pulitzer", journalist.to_param
|
411
457
|
assert journalist.valid?
|
412
458
|
assert journalist.persisted?
|
@@ -416,7 +462,137 @@ class FailedValidationAfterUpdateRegressionTest < TestCaseClass
|
|
416
462
|
assert_equal "joseph-pulitzer", journalist.to_param
|
417
463
|
end
|
418
464
|
end
|
465
|
+
end
|
466
|
+
|
467
|
+
# https://github.com/norman/friendly_id/issues/947
|
468
|
+
class GeneratingSlugWithValidationSkippedTest < TestCaseClass
|
469
|
+
include FriendlyId::Test
|
470
|
+
|
471
|
+
class Journalist < ActiveRecord::Base
|
472
|
+
extend FriendlyId
|
473
|
+
friendly_id :name, use: :slugged
|
474
|
+
end
|
475
|
+
|
476
|
+
test "should generate slug when skipping validation" do
|
477
|
+
transaction do
|
478
|
+
m1 = Journalist.new
|
479
|
+
m1.name = "Bob Timesletter"
|
480
|
+
m1.save(validate: false)
|
481
|
+
assert_equal "bob-timesletter", m1.slug
|
482
|
+
end
|
483
|
+
end
|
484
|
+
|
485
|
+
test "should generate slug when #valid? called" do
|
486
|
+
transaction do
|
487
|
+
m1 = Journalist.new
|
488
|
+
m1.name = "Bob Timesletter"
|
489
|
+
m1.valid?
|
490
|
+
m1.save(validate: false)
|
491
|
+
assert_equal "bob-timesletter", m1.slug
|
492
|
+
end
|
493
|
+
end
|
494
|
+
end
|
495
|
+
|
496
|
+
class ToParamTest < TestCaseClass
|
497
|
+
include FriendlyId::Test
|
498
|
+
|
499
|
+
class Journalist < ActiveRecord::Base
|
500
|
+
extend FriendlyId
|
501
|
+
validates_presence_of :active
|
502
|
+
validates_length_of :slug, minimum: 2
|
503
|
+
friendly_id :name, use: :slugged
|
504
|
+
|
505
|
+
attr_accessor :to_param_in_callback
|
506
|
+
|
507
|
+
after_save do
|
508
|
+
self.to_param_in_callback = to_param
|
509
|
+
end
|
510
|
+
end
|
511
|
+
|
512
|
+
test "to_param should return nil if record is unpersisted" do
|
513
|
+
assert_nil Journalist.new.to_param
|
514
|
+
end
|
515
|
+
|
516
|
+
test "to_param should return original slug if record failed validation" do
|
517
|
+
journalist = Journalist.new name: "Clark Kent", active: nil
|
518
|
+
refute journalist.save
|
519
|
+
assert_equal "clark-kent", journalist.to_param
|
520
|
+
end
|
419
521
|
|
522
|
+
test "to_param should clear slug attributes if slug attribute fails validation" do
|
523
|
+
journalist = Journalist.new name: "x", active: true
|
524
|
+
refute journalist.save
|
525
|
+
assert_nil journalist.to_param
|
526
|
+
end
|
527
|
+
|
528
|
+
test "to_param should clear slug attribute if slug attribute fails validation and unrelated validation fails" do
|
529
|
+
journalist = Journalist.new name: "x", active: nil
|
530
|
+
refute journalist.save
|
531
|
+
assert_nil journalist.to_param
|
532
|
+
end
|
533
|
+
|
534
|
+
test "to_param should use slugged attribute if record saved successfully" do
|
535
|
+
transaction do
|
536
|
+
journalist = Journalist.new name: "Clark Kent", active: true
|
537
|
+
assert journalist.save
|
538
|
+
assert_equal "clark-kent", journalist.to_param
|
539
|
+
end
|
540
|
+
end
|
541
|
+
|
542
|
+
test "to_param should use new slug if existing record changes but fails to save" do
|
543
|
+
transaction do
|
544
|
+
journalist = Journalist.new name: "Clark Kent", active: true
|
545
|
+
assert journalist.save
|
546
|
+
journalist.name = "Superman"
|
547
|
+
journalist.slug = nil
|
548
|
+
journalist.active = nil
|
549
|
+
refute journalist.save
|
550
|
+
assert_equal "superman", journalist.to_param
|
551
|
+
end
|
552
|
+
end
|
553
|
+
|
554
|
+
test "to_param should use original slug if new slug attribute is not valid" do
|
555
|
+
transaction do
|
556
|
+
journalist = Journalist.new name: "Clark Kent", active: true
|
557
|
+
assert journalist.save
|
558
|
+
journalist.name = "x"
|
559
|
+
journalist.slug = nil
|
560
|
+
journalist.active = nil
|
561
|
+
refute journalist.save
|
562
|
+
assert_equal "clark-kent", journalist.to_param
|
563
|
+
end
|
564
|
+
end
|
565
|
+
|
566
|
+
test "to_param should use new slug if existing record changes successfully" do
|
567
|
+
transaction do
|
568
|
+
journalist = Journalist.new name: "Clark Kent", active: true
|
569
|
+
assert journalist.save
|
570
|
+
journalist.name = "Superman"
|
571
|
+
journalist.slug = nil
|
572
|
+
assert journalist.save
|
573
|
+
assert_equal "superman", journalist.to_param
|
574
|
+
end
|
575
|
+
end
|
576
|
+
|
577
|
+
test "to_param should use new slug within callbacks if new record is saved successfully" do
|
578
|
+
transaction do
|
579
|
+
journalist = Journalist.new name: "Clark Kent", active: true
|
580
|
+
assert journalist.save
|
581
|
+
assert_equal "clark-kent", journalist.to_param_in_callback, "value of to_param in callback should use the new slug value"
|
582
|
+
end
|
583
|
+
end
|
584
|
+
|
585
|
+
test "to_param should use new slug within callbacks if existing record changes successfully" do
|
586
|
+
transaction do
|
587
|
+
journalist = Journalist.new name: "Clark Kent", active: true
|
588
|
+
assert journalist.save
|
589
|
+
assert journalist.valid?
|
590
|
+
journalist.name = "Superman"
|
591
|
+
journalist.slug = nil
|
592
|
+
assert journalist.save, "save should be successful"
|
593
|
+
assert_equal "superman", journalist.to_param_in_callback, "value of to_param in callback should use the new slug value"
|
594
|
+
end
|
595
|
+
end
|
420
596
|
end
|
421
597
|
|
422
598
|
class ConfigurableRoutesTest < TestCaseClass
|
@@ -425,18 +601,18 @@ class ConfigurableRoutesTest < TestCaseClass
|
|
425
601
|
class Article < ActiveRecord::Base
|
426
602
|
extend FriendlyId
|
427
603
|
|
428
|
-
friendly_id :name, :
|
604
|
+
friendly_id :name, use: :slugged, routes: :friendly
|
429
605
|
end
|
430
606
|
|
431
607
|
class Novel < ActiveRecord::Base
|
432
608
|
extend FriendlyId
|
433
609
|
|
434
|
-
friendly_id :name, :
|
610
|
+
friendly_id :name, use: :slugged, routes: :default
|
435
611
|
end
|
436
612
|
|
437
613
|
test "to_param should return a friendly id when the routes option is set to :friendly" do
|
438
614
|
transaction do
|
439
|
-
article = Article.create! :
|
615
|
+
article = Article.create! name: "Titanic Hits; Iceberg Sinks"
|
440
616
|
|
441
617
|
assert_equal "titanic-hits-iceberg-sinks", article.to_param
|
442
618
|
end
|
@@ -444,7 +620,7 @@ class ConfigurableRoutesTest < TestCaseClass
|
|
444
620
|
|
445
621
|
test "to_param should return the id when the routes option is set to anything but friendly" do
|
446
622
|
transaction do
|
447
|
-
novel = Novel.create! :
|
623
|
+
novel = Novel.create! name: "Don Quixote"
|
448
624
|
|
449
625
|
assert_equal novel.id.to_s, novel.to_param
|
450
626
|
end
|