friendly_id 5.6.0 → 5.7.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/lib/friendly_id/version.rb +1 -1
- metadata +2 -44
- data/.gemtest +0 -0
- data/.github/FUNDING.yml +0 -1
- data/.github/dependabot.yml +0 -6
- data/.github/stale.yml +0 -17
- data/.github/workflows/release.yml +0 -29
- data/.github/workflows/test.yml +0 -86
- data/.gitignore +0 -14
- data/.yardopts +0 -8
- data/CONTRIBUTING.md +0 -11
- data/Gemfile +0 -23
- data/Rakefile +0 -100
- data/UPGRADING.md +0 -115
- data/bench.rb +0 -84
- data/friendly_id.gemspec +0 -31
- data/gemfiles/Gemfile.rails-6.0.rb +0 -22
- data/gemfiles/Gemfile.rails-6.1.rb +0 -22
- data/gemfiles/Gemfile.rails-7.0.rb +0 -22
- data/gemfiles/Gemfile.rails-7.1.rb +0 -22
- data/gemfiles/Gemfile.rails-7.2.rb +0 -22
- data/gemfiles/Gemfile.rails-8.0.rb +0 -22
- data/guide.rb +0 -24
- data/test/base_test.rb +0 -69
- data/test/benchmarks/finders.rb +0 -90
- data/test/benchmarks/object_utils.rb +0 -56
- data/test/candidates_test.rb +0 -142
- data/test/configuration_test.rb +0 -60
- data/test/core_test.rb +0 -35
- data/test/databases.yml +0 -22
- data/test/finders_test.rb +0 -76
- data/test/generator_test.rb +0 -38
- data/test/helper.rb +0 -125
- data/test/history_test.rb +0 -434
- data/test/numeric_slug_test.rb +0 -100
- data/test/object_utils_test.rb +0 -27
- data/test/reserved_test.rb +0 -73
- data/test/schema.rb +0 -117
- data/test/scoped_test.rb +0 -95
- data/test/sequentially_slugged_test.rb +0 -214
- data/test/shared.rb +0 -181
- data/test/simple_i18n_test.rb +0 -144
- data/test/slugged_test.rb +0 -628
- data/test/sti_test.rb +0 -135
data/test/generator_test.rb
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
require "helper"
|
|
2
|
-
require "rails/generators"
|
|
3
|
-
require "generators/friendly_id_generator"
|
|
4
|
-
|
|
5
|
-
class FriendlyIdGeneratorTest < Rails::Generators::TestCase
|
|
6
|
-
tests FriendlyIdGenerator
|
|
7
|
-
destination File.expand_path("../../tmp", __FILE__)
|
|
8
|
-
|
|
9
|
-
setup :prepare_destination
|
|
10
|
-
|
|
11
|
-
test "should generate a migration" do
|
|
12
|
-
run_generator
|
|
13
|
-
assert_migration "db/migrate/create_friendly_id_slugs"
|
|
14
|
-
ensure
|
|
15
|
-
FileUtils.rm_rf destination_root
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
test "should skip the migration when told to do so" do
|
|
19
|
-
run_generator ["--skip-migration"]
|
|
20
|
-
assert_no_migration "db/migrate/create_friendly_id_slugs"
|
|
21
|
-
ensure
|
|
22
|
-
FileUtils.rm_rf destination_root
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
test "should generate an initializer" do
|
|
26
|
-
run_generator
|
|
27
|
-
assert_file "config/initializers/friendly_id.rb"
|
|
28
|
-
ensure
|
|
29
|
-
FileUtils.rm_rf destination_root
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
test "should skip the initializer when told to do so" do
|
|
33
|
-
run_generator ["--skip-initializer"]
|
|
34
|
-
assert_no_file "config/initializers/friendly_id.rb"
|
|
35
|
-
ensure
|
|
36
|
-
FileUtils.rm_rf destination_root
|
|
37
|
-
end
|
|
38
|
-
end
|
data/test/helper.rb
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
require "bundler/setup"
|
|
2
|
-
|
|
3
|
-
if ENV["COVERALLS"] || ENV["COVERAGE"]
|
|
4
|
-
require "simplecov"
|
|
5
|
-
if ENV["COVERALLS"]
|
|
6
|
-
require "coveralls"
|
|
7
|
-
SimpleCov.formatter = Coveralls::SimpleCov::Formatter
|
|
8
|
-
end
|
|
9
|
-
SimpleCov.start do
|
|
10
|
-
add_filter "test"
|
|
11
|
-
add_filter "friendly_id/migration"
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
begin
|
|
16
|
-
require "minitest"
|
|
17
|
-
rescue LoadError
|
|
18
|
-
require "minitest/unit"
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
begin
|
|
22
|
-
TestCaseClass = Minitest::Test
|
|
23
|
-
rescue NameError
|
|
24
|
-
TestCaseClass = Minitest::Unit::TestCase
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
require "mocha/minitest"
|
|
28
|
-
require "active_record"
|
|
29
|
-
require "active_support/core_ext/time/conversions"
|
|
30
|
-
require "erb"
|
|
31
|
-
|
|
32
|
-
I18n.enforce_available_locales = false
|
|
33
|
-
|
|
34
|
-
require "friendly_id"
|
|
35
|
-
|
|
36
|
-
# If you want to see the ActiveRecord log, invoke the tests using `rake test LOG=true`
|
|
37
|
-
if ENV["LOG"]
|
|
38
|
-
require "logger"
|
|
39
|
-
ActiveRecord::Base.logger = Logger.new($stdout)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
if ActiveSupport::VERSION::STRING >= "4.2"
|
|
43
|
-
ActiveSupport.test_order = :random
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
module FriendlyId
|
|
47
|
-
module Test
|
|
48
|
-
def self.included(base)
|
|
49
|
-
if Minitest.respond_to?(:autorun)
|
|
50
|
-
Minitest.autorun
|
|
51
|
-
else
|
|
52
|
-
require "minitest/autorun"
|
|
53
|
-
end
|
|
54
|
-
rescue LoadError
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def transaction
|
|
58
|
-
ActiveRecord::Base.transaction do
|
|
59
|
-
yield
|
|
60
|
-
|
|
61
|
-
raise ActiveRecord::Rollback
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def with_instance_of(*args)
|
|
66
|
-
model_class = args.shift
|
|
67
|
-
args[0] ||= {name: "a b c"}
|
|
68
|
-
transaction { yield model_class.create!(*args) }
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
module Database
|
|
72
|
-
extend self
|
|
73
|
-
|
|
74
|
-
def connect
|
|
75
|
-
version = ActiveRecord::VERSION::STRING
|
|
76
|
-
engine = begin
|
|
77
|
-
RUBY_ENGINE
|
|
78
|
-
rescue
|
|
79
|
-
"ruby"
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
ActiveRecord::Base.establish_connection config[driver]
|
|
83
|
-
message = "Using #{engine} #{RUBY_VERSION} AR #{version} with #{driver}"
|
|
84
|
-
|
|
85
|
-
puts "-" * 72
|
|
86
|
-
if in_memory?
|
|
87
|
-
ActiveRecord::Migration.verbose = false
|
|
88
|
-
Schema.migrate :up
|
|
89
|
-
puts "#{message} (in-memory)"
|
|
90
|
-
else
|
|
91
|
-
puts message
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def config
|
|
96
|
-
@config ||= YAML.safe_load(
|
|
97
|
-
ERB.new(
|
|
98
|
-
File.read(File.expand_path("../databases.yml", __FILE__))
|
|
99
|
-
).result
|
|
100
|
-
)
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def driver
|
|
104
|
-
db_driver = ENV.fetch("DB", "sqlite3").downcase
|
|
105
|
-
db_driver = "postgres" if %w[postgresql pg].include?(db_driver)
|
|
106
|
-
db_driver
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
def in_memory?
|
|
110
|
-
config[driver]["database"] == ":memory:"
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
class Module
|
|
117
|
-
def test(name, &block)
|
|
118
|
-
define_method("test_#{name.gsub(/[^a-z0-9']/i, "_")}".to_sym, &block)
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
require "schema"
|
|
123
|
-
require "shared"
|
|
124
|
-
FriendlyId::Test::Database.connect
|
|
125
|
-
at_exit { ActiveRecord::Base.connection.disconnect! }
|
data/test/history_test.rb
DELETED
|
@@ -1,434 +0,0 @@
|
|
|
1
|
-
require "helper"
|
|
2
|
-
|
|
3
|
-
class HistoryTest < TestCaseClass
|
|
4
|
-
include FriendlyId::Test
|
|
5
|
-
include FriendlyId::Test::Shared::Core
|
|
6
|
-
|
|
7
|
-
class Manual < ActiveRecord::Base
|
|
8
|
-
extend FriendlyId
|
|
9
|
-
friendly_id :name, use: [:slugged, :history]
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def model_class
|
|
13
|
-
Manual
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
test "should insert record in slugs table on create" do
|
|
17
|
-
with_instance_of(model_class) { |record| assert record.slugs.any? }
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
test "should not create new slug record if friendly_id is not changed" do
|
|
21
|
-
with_instance_of(model_class) do |record|
|
|
22
|
-
record.active = true
|
|
23
|
-
record.save!
|
|
24
|
-
assert_equal 1, FriendlyId::Slug.count
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
test "should create new slug record when friendly_id changes" do
|
|
29
|
-
with_instance_of(model_class) do |record|
|
|
30
|
-
record.name = record.name + "b"
|
|
31
|
-
record.slug = nil
|
|
32
|
-
record.save!
|
|
33
|
-
assert_equal 2, FriendlyId::Slug.count
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
test "should be findable by old slugs" do
|
|
38
|
-
with_instance_of(model_class) do |record|
|
|
39
|
-
old_friendly_id = record.friendly_id
|
|
40
|
-
record.name = record.name + "b"
|
|
41
|
-
record.slug = nil
|
|
42
|
-
record.save!
|
|
43
|
-
begin
|
|
44
|
-
assert model_class.friendly.find(old_friendly_id)
|
|
45
|
-
assert model_class.friendly.exists?(old_friendly_id), "should exist? by old id"
|
|
46
|
-
rescue ActiveRecord::RecordNotFound
|
|
47
|
-
flunk "Could not find record by old id"
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
test "should create slug records on each change" do
|
|
53
|
-
transaction do
|
|
54
|
-
model_class.create! name: "hello"
|
|
55
|
-
assert_equal 1, FriendlyId::Slug.count
|
|
56
|
-
|
|
57
|
-
record = model_class.friendly.find("hello")
|
|
58
|
-
record.name = "hello again"
|
|
59
|
-
record.slug = nil
|
|
60
|
-
record.save!
|
|
61
|
-
assert_equal 2, FriendlyId::Slug.count
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
test "should not be read only when found by slug" do
|
|
66
|
-
with_instance_of(model_class) do |record|
|
|
67
|
-
refute model_class.friendly.find(record.friendly_id).readonly?
|
|
68
|
-
assert record.update name: "foo"
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
test "should not be read only when found by old slug" do
|
|
73
|
-
with_instance_of(model_class) do |record|
|
|
74
|
-
old_friendly_id = record.friendly_id
|
|
75
|
-
record.name = record.name + "b"
|
|
76
|
-
record.save!
|
|
77
|
-
assert !model_class.friendly.find(old_friendly_id).readonly?
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
test "should handle renames" do
|
|
82
|
-
with_instance_of(model_class) do |record|
|
|
83
|
-
record.name = "x"
|
|
84
|
-
record.slug = nil
|
|
85
|
-
assert record.save
|
|
86
|
-
record.name = "y"
|
|
87
|
-
record.slug = nil
|
|
88
|
-
assert record.save
|
|
89
|
-
record.name = "x"
|
|
90
|
-
record.slug = nil
|
|
91
|
-
assert record.save
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
test "should maintain history even if current slug is not the most recent one" do
|
|
96
|
-
with_instance_of(model_class) do |record|
|
|
97
|
-
record.name = "current"
|
|
98
|
-
assert record.save
|
|
99
|
-
|
|
100
|
-
# this feels like a hack. only thing i can get to work with the HistoryTestWithSti
|
|
101
|
-
# test cases. (Editorialist vs Journalist.)
|
|
102
|
-
sluggable_type = FriendlyId::Slug.first.sluggable_type
|
|
103
|
-
# create several slugs for record
|
|
104
|
-
# current slug does not have max id
|
|
105
|
-
FriendlyId::Slug.delete_all
|
|
106
|
-
FriendlyId::Slug.create(sluggable_type: sluggable_type, sluggable_id: record.id, slug: "current")
|
|
107
|
-
FriendlyId::Slug.create(sluggable_type: sluggable_type, sluggable_id: record.id, slug: "outdated")
|
|
108
|
-
|
|
109
|
-
record.reload
|
|
110
|
-
record.slug = nil
|
|
111
|
-
assert record.save
|
|
112
|
-
|
|
113
|
-
assert_equal 2, FriendlyId::Slug.count
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
test "should not create new slugs that match old slugs" do
|
|
118
|
-
transaction do
|
|
119
|
-
first_record = model_class.create! name: "foo"
|
|
120
|
-
first_record.name = "bar"
|
|
121
|
-
first_record.save!
|
|
122
|
-
second_record = model_class.create! name: "foo"
|
|
123
|
-
assert second_record.slug != "foo"
|
|
124
|
-
assert_match(/foo-.+/, second_record.slug)
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
test "should not fail when updating historic slugs" do
|
|
129
|
-
transaction do
|
|
130
|
-
first_record = model_class.create! name: "foo"
|
|
131
|
-
second_record = model_class.create! name: "another"
|
|
132
|
-
|
|
133
|
-
second_record.update name: "foo", slug: nil
|
|
134
|
-
assert_match(/foo-.*/, second_record.slug)
|
|
135
|
-
|
|
136
|
-
first_record.update name: "another", slug: nil
|
|
137
|
-
assert_match(/another-.*/, first_record.slug)
|
|
138
|
-
end
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
test "should prefer product that used slug most recently" do
|
|
142
|
-
transaction do
|
|
143
|
-
first_record = model_class.create! name: "foo"
|
|
144
|
-
second_record = model_class.create! name: "bar"
|
|
145
|
-
|
|
146
|
-
first_record.update! slug: "not_foo"
|
|
147
|
-
second_record.update! slug: "foo" # now both records have used foo; second_record most recently
|
|
148
|
-
second_record.update! slug: "not_bar"
|
|
149
|
-
|
|
150
|
-
assert_equal model_class.friendly.find("foo"), second_record
|
|
151
|
-
end
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
test "should name table according to prefix and suffix" do
|
|
155
|
-
transaction do
|
|
156
|
-
prefix = "prefix_"
|
|
157
|
-
without_prefix = FriendlyId::Slug.table_name
|
|
158
|
-
ActiveRecord::Base.table_name_prefix = prefix
|
|
159
|
-
FriendlyId::Slug.reset_table_name
|
|
160
|
-
assert_equal prefix + without_prefix, FriendlyId::Slug.table_name
|
|
161
|
-
ensure
|
|
162
|
-
ActiveRecord::Base.table_name_prefix = ""
|
|
163
|
-
FriendlyId::Slug.table_name = without_prefix
|
|
164
|
-
end
|
|
165
|
-
end
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
class HistoryTestWithAutomaticSlugRegeneration < HistoryTest
|
|
169
|
-
class Manual < ActiveRecord::Base
|
|
170
|
-
extend FriendlyId
|
|
171
|
-
friendly_id :name, use: [:slugged, :history]
|
|
172
|
-
|
|
173
|
-
def should_generate_new_friendly_id?
|
|
174
|
-
slug.blank? or name_changed?
|
|
175
|
-
end
|
|
176
|
-
end
|
|
177
|
-
|
|
178
|
-
def model_class
|
|
179
|
-
Manual
|
|
180
|
-
end
|
|
181
|
-
|
|
182
|
-
test "should allow reversion back to a previously used slug" do
|
|
183
|
-
with_instance_of(model_class, name: "foo") do |record|
|
|
184
|
-
record.name = "bar"
|
|
185
|
-
record.save!
|
|
186
|
-
assert_equal "bar", record.friendly_id
|
|
187
|
-
record.name = "foo"
|
|
188
|
-
record.save!
|
|
189
|
-
assert_equal "foo", record.friendly_id
|
|
190
|
-
end
|
|
191
|
-
end
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
class DependentDestroyTest < TestCaseClass
|
|
195
|
-
include FriendlyId::Test
|
|
196
|
-
|
|
197
|
-
class FalseManual < ActiveRecord::Base
|
|
198
|
-
self.table_name = "manuals"
|
|
199
|
-
|
|
200
|
-
extend FriendlyId
|
|
201
|
-
friendly_id :name, use: :history, dependent: false
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
class DefaultManual < ActiveRecord::Base
|
|
205
|
-
self.table_name = "manuals"
|
|
206
|
-
|
|
207
|
-
extend FriendlyId
|
|
208
|
-
friendly_id :name, use: :history
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
test "should allow disabling of dependent destroy" do
|
|
212
|
-
transaction do
|
|
213
|
-
assert FriendlyId::Slug.find_by_slug("foo").nil?
|
|
214
|
-
l = FalseManual.create! name: "foo"
|
|
215
|
-
assert FriendlyId::Slug.find_by_slug("foo").present?
|
|
216
|
-
l.destroy
|
|
217
|
-
assert FriendlyId::Slug.find_by_slug("foo").present?
|
|
218
|
-
end
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
test "should dependently destroy by default" do
|
|
222
|
-
transaction do
|
|
223
|
-
assert FriendlyId::Slug.find_by_slug("baz").nil?
|
|
224
|
-
l = DefaultManual.create! name: "baz"
|
|
225
|
-
assert FriendlyId::Slug.find_by_slug("baz").present?
|
|
226
|
-
l.destroy
|
|
227
|
-
assert FriendlyId::Slug.find_by_slug("baz").nil?
|
|
228
|
-
end
|
|
229
|
-
end
|
|
230
|
-
end
|
|
231
|
-
|
|
232
|
-
if ActiveRecord::VERSION::STRING >= "5.0"
|
|
233
|
-
class HistoryTestWithParanoidDeletes < HistoryTest
|
|
234
|
-
class ParanoidRecord < ActiveRecord::Base
|
|
235
|
-
extend FriendlyId
|
|
236
|
-
friendly_id :name, use: :history, dependent: false
|
|
237
|
-
|
|
238
|
-
default_scope { where(deleted_at: nil) }
|
|
239
|
-
end
|
|
240
|
-
|
|
241
|
-
def model_class
|
|
242
|
-
ParanoidRecord
|
|
243
|
-
end
|
|
244
|
-
|
|
245
|
-
test "slug should have a sluggable even when soft deleted by a library" do
|
|
246
|
-
transaction do
|
|
247
|
-
assert FriendlyId::Slug.find_by_slug("paranoid").nil?
|
|
248
|
-
record = model_class.create(name: "paranoid")
|
|
249
|
-
assert FriendlyId::Slug.find_by_slug("paranoid").present?
|
|
250
|
-
|
|
251
|
-
record.update deleted_at: Time.now
|
|
252
|
-
|
|
253
|
-
orphan_slug = FriendlyId::Slug.find_by_slug("paranoid")
|
|
254
|
-
assert orphan_slug.present?, "Orphaned slug should exist"
|
|
255
|
-
|
|
256
|
-
assert orphan_slug.valid?, "Errors: #{orphan_slug.errors.full_messages}"
|
|
257
|
-
assert orphan_slug.sluggable.present?, "Orphaned slug should still find corresponding paranoid sluggable"
|
|
258
|
-
end
|
|
259
|
-
end
|
|
260
|
-
end
|
|
261
|
-
end
|
|
262
|
-
|
|
263
|
-
class HistoryTestWithSti < HistoryTest
|
|
264
|
-
class Journalist < ActiveRecord::Base
|
|
265
|
-
extend FriendlyId
|
|
266
|
-
friendly_id :name, use: [:slugged, :history]
|
|
267
|
-
end
|
|
268
|
-
|
|
269
|
-
class Editorialist < Journalist
|
|
270
|
-
end
|
|
271
|
-
|
|
272
|
-
def model_class
|
|
273
|
-
Editorialist
|
|
274
|
-
end
|
|
275
|
-
end
|
|
276
|
-
|
|
277
|
-
class HistoryTestWithFriendlyFinders < HistoryTest
|
|
278
|
-
class Journalist < ActiveRecord::Base
|
|
279
|
-
extend FriendlyId
|
|
280
|
-
friendly_id :name, use: [:slugged, :finders, :history]
|
|
281
|
-
end
|
|
282
|
-
|
|
283
|
-
class Restaurant < ActiveRecord::Base
|
|
284
|
-
extend FriendlyId
|
|
285
|
-
belongs_to :city
|
|
286
|
-
friendly_id :name, use: [:slugged, :history, :finders]
|
|
287
|
-
end
|
|
288
|
-
|
|
289
|
-
test "should be findable by old slugs" do
|
|
290
|
-
[Journalist, Restaurant].each do |model_class|
|
|
291
|
-
with_instance_of(model_class) do |record|
|
|
292
|
-
old_friendly_id = record.friendly_id
|
|
293
|
-
record.name = record.name + "b"
|
|
294
|
-
record.slug = nil
|
|
295
|
-
record.save!
|
|
296
|
-
begin
|
|
297
|
-
assert model_class.find(old_friendly_id)
|
|
298
|
-
assert model_class.exists?(old_friendly_id), "should exist? by old id for #{model_class.name}"
|
|
299
|
-
rescue ActiveRecord::RecordNotFound
|
|
300
|
-
flunk "Could not find record by old id for #{model_class.name}"
|
|
301
|
-
end
|
|
302
|
-
end
|
|
303
|
-
end
|
|
304
|
-
end
|
|
305
|
-
end
|
|
306
|
-
|
|
307
|
-
class HistoryTestWithFindersBeforeHistory < HistoryTest
|
|
308
|
-
class Novelist < ActiveRecord::Base
|
|
309
|
-
has_many :novels
|
|
310
|
-
end
|
|
311
|
-
|
|
312
|
-
class Novel < ActiveRecord::Base
|
|
313
|
-
extend FriendlyId
|
|
314
|
-
|
|
315
|
-
belongs_to :novelist
|
|
316
|
-
|
|
317
|
-
friendly_id :name, use: [:finders, :history]
|
|
318
|
-
|
|
319
|
-
def should_generate_new_friendly_id?
|
|
320
|
-
slug.blank? || name_changed?
|
|
321
|
-
end
|
|
322
|
-
end
|
|
323
|
-
|
|
324
|
-
test "should be findable by old slug through has_many association" do
|
|
325
|
-
transaction do
|
|
326
|
-
novelist = Novelist.create!(name: "Stephen King")
|
|
327
|
-
novel = novelist.novels.create(name: "Rita Hayworth and Shawshank Redemption")
|
|
328
|
-
slug = novel.slug
|
|
329
|
-
novel.name = "Shawshank Redemption"
|
|
330
|
-
novel.save!
|
|
331
|
-
assert_equal novel, Novel.find(slug)
|
|
332
|
-
assert_equal novel, novelist.novels.find(slug)
|
|
333
|
-
end
|
|
334
|
-
end
|
|
335
|
-
end
|
|
336
|
-
|
|
337
|
-
class City < ActiveRecord::Base
|
|
338
|
-
has_many :restaurants
|
|
339
|
-
end
|
|
340
|
-
|
|
341
|
-
class Restaurant < ActiveRecord::Base
|
|
342
|
-
extend FriendlyId
|
|
343
|
-
belongs_to :city
|
|
344
|
-
friendly_id :name, use: [:scoped, :history], scope: :city
|
|
345
|
-
end
|
|
346
|
-
|
|
347
|
-
class ScopedHistoryTest < TestCaseClass
|
|
348
|
-
include FriendlyId::Test
|
|
349
|
-
include FriendlyId::Test::Shared::Core
|
|
350
|
-
|
|
351
|
-
def model_class
|
|
352
|
-
Restaurant
|
|
353
|
-
end
|
|
354
|
-
|
|
355
|
-
test "should find old scoped slugs" do
|
|
356
|
-
transaction do
|
|
357
|
-
city = City.create!
|
|
358
|
-
with_instance_of(Restaurant) do |record|
|
|
359
|
-
record.city = city
|
|
360
|
-
|
|
361
|
-
record.name = "x"
|
|
362
|
-
record.slug = nil
|
|
363
|
-
record.save!
|
|
364
|
-
|
|
365
|
-
record.name = "y"
|
|
366
|
-
record.slug = nil
|
|
367
|
-
record.save!
|
|
368
|
-
|
|
369
|
-
assert_equal city.restaurants.friendly.find("x"), city.restaurants.friendly.find("y")
|
|
370
|
-
end
|
|
371
|
-
end
|
|
372
|
-
end
|
|
373
|
-
|
|
374
|
-
test "should consider old scoped slugs when creating slugs" do
|
|
375
|
-
transaction do
|
|
376
|
-
city = City.create!
|
|
377
|
-
with_instance_of(Restaurant) do |record|
|
|
378
|
-
record.city = city
|
|
379
|
-
|
|
380
|
-
record.name = "x"
|
|
381
|
-
record.slug = nil
|
|
382
|
-
record.save!
|
|
383
|
-
|
|
384
|
-
record.name = "y"
|
|
385
|
-
record.slug = nil
|
|
386
|
-
record.save!
|
|
387
|
-
|
|
388
|
-
second_record = model_class.create! city: city, name: "x"
|
|
389
|
-
assert_match(/x-.+/, second_record.friendly_id)
|
|
390
|
-
|
|
391
|
-
third_record = model_class.create! city: city, name: "y"
|
|
392
|
-
assert_match(/y-.+/, third_record.friendly_id)
|
|
393
|
-
end
|
|
394
|
-
end
|
|
395
|
-
end
|
|
396
|
-
|
|
397
|
-
test "should record history when scope changes" do
|
|
398
|
-
transaction do
|
|
399
|
-
city1 = City.create!
|
|
400
|
-
city2 = City.create!
|
|
401
|
-
with_instance_of(Restaurant) do |record|
|
|
402
|
-
record.name = "x"
|
|
403
|
-
record.slug = nil
|
|
404
|
-
|
|
405
|
-
record.city = city1
|
|
406
|
-
record.save!
|
|
407
|
-
assert_equal("city_id:#{city1.id}", record.slugs.reload.first.scope)
|
|
408
|
-
assert_equal("x", record.slugs.reload.first.slug)
|
|
409
|
-
|
|
410
|
-
record.city = city2
|
|
411
|
-
record.save!
|
|
412
|
-
assert_equal("city_id:#{city2.id}", record.slugs.reload.first.scope)
|
|
413
|
-
|
|
414
|
-
record.name = "y"
|
|
415
|
-
record.slug = nil
|
|
416
|
-
record.city = city1
|
|
417
|
-
record.save!
|
|
418
|
-
assert_equal("city_id:#{city1.id}", record.slugs.reload.first.scope)
|
|
419
|
-
assert_equal("y", record.slugs.reload.first.slug)
|
|
420
|
-
end
|
|
421
|
-
end
|
|
422
|
-
end
|
|
423
|
-
|
|
424
|
-
test "should allow equal slugs in different scopes" do
|
|
425
|
-
transaction do
|
|
426
|
-
city = City.create!
|
|
427
|
-
second_city = City.create!
|
|
428
|
-
record = model_class.create! city: city, name: "x"
|
|
429
|
-
second_record = model_class.create! city: second_city, name: "x"
|
|
430
|
-
|
|
431
|
-
assert_equal record.slug, second_record.slug
|
|
432
|
-
end
|
|
433
|
-
end
|
|
434
|
-
end
|
data/test/numeric_slug_test.rb
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
require "helper"
|
|
2
|
-
|
|
3
|
-
class Article < ActiveRecord::Base
|
|
4
|
-
extend FriendlyId
|
|
5
|
-
friendly_id :name, use: :slugged
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
class ArticleWithNumericPrevention < ActiveRecord::Base
|
|
9
|
-
self.table_name = "articles"
|
|
10
|
-
extend FriendlyId
|
|
11
|
-
friendly_id :name, use: :slugged
|
|
12
|
-
friendly_id_config.treat_numeric_as_conflict = true
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
class NumericSlugTest < TestCaseClass
|
|
16
|
-
include FriendlyId::Test
|
|
17
|
-
include FriendlyId::Test::Shared::Core
|
|
18
|
-
|
|
19
|
-
def model_class
|
|
20
|
-
Article
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
test "should generate numeric slugs" do
|
|
24
|
-
transaction do
|
|
25
|
-
record = model_class.create! name: "123"
|
|
26
|
-
assert_equal "123", record.slug
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
test "should find by numeric slug" do
|
|
31
|
-
transaction do
|
|
32
|
-
record = model_class.create! name: "123"
|
|
33
|
-
assert_equal model_class.friendly.find("123").id, record.id
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
test "should exist? by numeric slug" do
|
|
38
|
-
transaction do
|
|
39
|
-
model_class.create! name: "123"
|
|
40
|
-
assert model_class.friendly.exists?("123")
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
test "should prevent purely numeric slugs when treat_numeric_as_conflict is enabled" do
|
|
45
|
-
transaction do
|
|
46
|
-
record = ArticleWithNumericPrevention.create! name: "123"
|
|
47
|
-
refute_equal "123", record.slug
|
|
48
|
-
assert_match(/\A123-[0-9a-f-]{36}\z/, record.slug)
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
test "should allow non-numeric slugs when treat_numeric_as_conflict is enabled" do
|
|
53
|
-
transaction do
|
|
54
|
-
record = ArticleWithNumericPrevention.create! name: "abc123"
|
|
55
|
-
assert_equal "abc123", record.slug
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
test "should allow alphanumeric slugs when treat_numeric_as_conflict is enabled" do
|
|
60
|
-
transaction do
|
|
61
|
-
record = ArticleWithNumericPrevention.create! name: "product-123"
|
|
62
|
-
assert_equal "product-123", record.slug
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
test "should handle zero as numeric when treat_numeric_as_conflict is enabled" do
|
|
67
|
-
transaction do
|
|
68
|
-
record = ArticleWithNumericPrevention.create! name: "0"
|
|
69
|
-
refute_equal "0", record.slug
|
|
70
|
-
assert_match(/\A0-[0-9a-f-]{36}\z/, record.slug)
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
test "should handle large numbers as numeric when treat_numeric_as_conflict is enabled" do
|
|
75
|
-
transaction do
|
|
76
|
-
record = ArticleWithNumericPrevention.create! name: "999999999"
|
|
77
|
-
refute_equal "999999999", record.slug
|
|
78
|
-
assert_match(/\A999999999-[0-9a-f-]{36}\z/, record.slug)
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
test "should find records with UUID-suffixed numeric slugs when treat_numeric_as_conflict is enabled" do
|
|
83
|
-
transaction do
|
|
84
|
-
record = ArticleWithNumericPrevention.create! name: "123"
|
|
85
|
-
found = ArticleWithNumericPrevention.friendly.find(record.slug)
|
|
86
|
-
assert_equal record.id, found.id
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
test "should resolve conflicts between multiple numeric slugs when treat_numeric_as_conflict is enabled" do
|
|
91
|
-
transaction do
|
|
92
|
-
record1 = ArticleWithNumericPrevention.create! name: "456"
|
|
93
|
-
record2 = ArticleWithNumericPrevention.create! name: "456"
|
|
94
|
-
|
|
95
|
-
refute_equal record1.slug, record2.slug
|
|
96
|
-
assert_match(/\A456-[0-9a-f-]{36}\z/, record1.slug)
|
|
97
|
-
assert_match(/\A456-[0-9a-f-]{36}\z/, record2.slug)
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
end
|