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.
Files changed (68) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/FUNDING.yml +1 -0
  4. data/.github/dependabot.yml +6 -0
  5. data/.github/stale.yml +17 -0
  6. data/.github/workflows/test.yml +58 -0
  7. data/Changelog.md +41 -0
  8. data/Gemfile +10 -11
  9. data/README.md +42 -15
  10. data/Rakefile +24 -27
  11. data/bench.rb +30 -27
  12. data/certs/parndt.pem +27 -0
  13. data/friendly_id.gemspec +28 -27
  14. data/gemfiles/Gemfile.rails-5.2.rb +11 -16
  15. data/gemfiles/Gemfile.rails-6.0.rb +22 -0
  16. data/gemfiles/Gemfile.rails-6.1.rb +22 -0
  17. data/gemfiles/Gemfile.rails-7.0.rb +22 -0
  18. data/guide.rb +5 -5
  19. data/lib/friendly_id/base.rb +61 -68
  20. data/lib/friendly_id/candidates.rb +9 -11
  21. data/lib/friendly_id/configuration.rb +8 -8
  22. data/lib/friendly_id/finder_methods.rb +72 -13
  23. data/lib/friendly_id/finders.rb +64 -67
  24. data/lib/friendly_id/history.rb +72 -66
  25. data/lib/friendly_id/initializer.rb +5 -5
  26. data/lib/friendly_id/migration.rb +10 -11
  27. data/lib/friendly_id/object_utils.rb +2 -2
  28. data/lib/friendly_id/reserved.rb +28 -32
  29. data/lib/friendly_id/scoped.rb +105 -103
  30. data/lib/friendly_id/sequentially_slugged/calculator.rb +69 -0
  31. data/lib/friendly_id/sequentially_slugged.rb +21 -58
  32. data/lib/friendly_id/simple_i18n.rb +75 -69
  33. data/lib/friendly_id/slug.rb +1 -2
  34. data/lib/friendly_id/slug_generator.rb +1 -3
  35. data/lib/friendly_id/slugged.rb +236 -239
  36. data/lib/friendly_id/version.rb +1 -1
  37. data/lib/friendly_id.rb +41 -45
  38. data/lib/generators/friendly_id_generator.rb +9 -9
  39. data/test/base_test.rb +10 -13
  40. data/test/benchmarks/finders.rb +28 -26
  41. data/test/benchmarks/object_utils.rb +13 -13
  42. data/test/candidates_test.rb +17 -18
  43. data/test/configuration_test.rb +7 -11
  44. data/test/core_test.rb +1 -2
  45. data/test/databases.yml +7 -4
  46. data/test/finders_test.rb +52 -5
  47. data/test/generator_test.rb +16 -26
  48. data/test/helper.rb +33 -20
  49. data/test/history_test.rb +116 -72
  50. data/test/numeric_slug_test.rb +31 -0
  51. data/test/object_utils_test.rb +0 -2
  52. data/test/reserved_test.rb +9 -11
  53. data/test/schema.rb +5 -4
  54. data/test/scoped_test.rb +26 -15
  55. data/test/sequentially_slugged_test.rb +107 -33
  56. data/test/shared.rb +17 -18
  57. data/test/simple_i18n_test.rb +23 -13
  58. data/test/slugged_test.rb +254 -78
  59. data/test/sti_test.rb +19 -21
  60. data.tar.gz.sig +0 -0
  61. metadata +49 -19
  62. metadata.gz.sig +1 -0
  63. data/.travis.yml +0 -57
  64. data/gemfiles/Gemfile.rails-4.0.rb +0 -30
  65. data/gemfiles/Gemfile.rails-4.1.rb +0 -29
  66. data/gemfiles/Gemfile.rails-4.2.rb +0 -28
  67. data/gemfiles/Gemfile.rails-5.0.rb +0 -28
  68. 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, :use => :slugged
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, :use => :slugged
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, :use => :slugged, :sequence_separator => '_'
15
+ friendly_id :name, use: :slugged, sequence_separator: "_"
16
16
 
17
17
  def normalize_friendly_id(string)
18
- super.gsub("-", "_")
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, :use => :slugged
37
- validates_length_of :slug, :maximum => 1
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 :name => "hello"
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, :use => :slugged
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! :name => "hello", :slug_en => "hello"
66
- instance2 = model_class.create :name => "hello", :slug_en => "hello"
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 'should allow a record to reuse its own slug' do
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 not set slug on create if unrelated validations fail" do
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
- friendly_id :name, :use => :slugged
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 :name => 'foo'
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 not set slug on create if unrelated validations fail with custom slug_column" do
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 = 'authors'
133
+ self.table_name = "authors"
116
134
  extend FriendlyId
117
135
  validates_presence_of :active
118
- friendly_id :name, :use => :slugged, :slug_column => :subdomain
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 :name => 'foo'
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 not update slug on save if unrelated validations fail" do
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, :use => :slugged
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 :name => 'foo', :active => true
182
+ instance = klass.new name: "foo", active: true
145
183
  assert instance.save
146
184
  assert instance.valid?
147
- instance.name = 'foobar'
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 'foo', instance.slug
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, :use => :slugged, :slug_column => "strange 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! :name => "a b c d"
245
+ m1 = model_class.create! name: "a b c d"
188
246
  assert_equal "a-b-c-d", m1.slug
189
- model_class.create! :name => "a b c d"
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! :name => "Peugeot 206"
256
+ record1 = model_class.create! name: "Peugeot 206"
199
257
  assert_equal "peugeot-206", record1.slug
200
- record2 = model_class.create! :name => "Peugeot 206"
201
- assert_match(/\Apeugeot-206-([a-z0-9]+\-){4}[a-z0-9]+\z/, record2.slug)
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! :name => 'wordsfail, buildings tumble'
208
- record2 = Novelist.create! :name => 'word fail'
209
- assert_equal 'word_fail', record2.slug
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 :name => '123'}.last
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, :use => :slugged, :sequence_separator => ":"
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! :name => record.name
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, :use => :slugged, :sequence_separator => '-'
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! :name => "Peugeot 206"
315
+ record1 = model_class.create! name: "Peugeot 206"
260
316
  assert_equal "peugeot-206", record1.slug
261
- record2 = model_class.create! :name => "Peugeot 206"
262
- assert_match(/\Apeugeot-206-([a-z0-9]+\-){4}[a-z0-9]+\z/, record2.slug)
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, :name => "" do |record|
268
- assert_match(/\A([a-z0-9]+\-){4}[a-z0-9]+\z/, record.slug)
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, :use => :slugged, :slug_limit => 40
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! :name => 'a' * 50
290
- assert_equal m1.slug, 'a' * 40
291
- m2 = model_class.create! :name => m1.name
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}\-/, m2.slug)
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, :use => :slugged
306
- default_scope -> { where(:active => true).order('id ASC') }
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 :name => "a", :active => true }
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 :name => "a", :active => false
318
- assert Journalist.create :name => "a", :active => true
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, :use => :slugged
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, :use => :slugged, :sequence_separator => "_"
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
- begin
386
- assert Manual.create! :name => "foo"
387
- rescue
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, :use => :slugged
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! :name => "Joseph Pulitzer", :slug_de => "value"
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, :use => :slugged, :routes => :friendly
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, :use => :slugged, :routes => :default
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! :name => "Titanic Hits; Iceberg Sinks"
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! :name => "Don Quixote"
623
+ novel = Novel.create! name: "Don Quixote"
448
624
 
449
625
  assert_equal novel.id.to_s, novel.to_param
450
626
  end