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/object_utils_test.rb
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
require "helper"
|
|
2
|
-
|
|
3
|
-
class ObjectUtilsTest < TestCaseClass
|
|
4
|
-
include FriendlyId::Test
|
|
5
|
-
|
|
6
|
-
test "strings with letters are friendly_ids" do
|
|
7
|
-
assert "a".friendly_id?
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
test "integers should be unfriendly ids" do
|
|
11
|
-
assert 1.unfriendly_id?
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
test "numeric strings are neither friendly nor unfriendly" do
|
|
15
|
-
assert_nil "1".friendly_id?
|
|
16
|
-
assert_nil "1".unfriendly_id?
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
test "ActiveRecord::Base instances should be unfriendly_ids" do
|
|
20
|
-
FriendlyId.mark_as_unfriendly(ActiveRecord::Base)
|
|
21
|
-
|
|
22
|
-
model_class = Class.new(ActiveRecord::Base) do
|
|
23
|
-
self.table_name = "authors"
|
|
24
|
-
end
|
|
25
|
-
assert model_class.new.unfriendly_id?
|
|
26
|
-
end
|
|
27
|
-
end
|
data/test/reserved_test.rb
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
require "helper"
|
|
2
|
-
|
|
3
|
-
class ReservedTest < TestCaseClass
|
|
4
|
-
include FriendlyId::Test
|
|
5
|
-
|
|
6
|
-
class Journalist < ActiveRecord::Base
|
|
7
|
-
extend FriendlyId
|
|
8
|
-
friendly_id :slug_candidates, use: [:slugged, :reserved], reserved_words: %w[new edit]
|
|
9
|
-
|
|
10
|
-
after_validation :move_friendly_id_error_to_name
|
|
11
|
-
|
|
12
|
-
def move_friendly_id_error_to_name
|
|
13
|
-
errors.add :name, *errors.delete(:friendly_id) if errors[:friendly_id].present?
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def slug_candidates
|
|
17
|
-
name
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def model_class
|
|
22
|
-
Journalist
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
test "should reserve words" do
|
|
26
|
-
%w[new edit NEW Edit].each do |word|
|
|
27
|
-
transaction do
|
|
28
|
-
assert_raises(ActiveRecord::RecordInvalid) { model_class.create! name: word }
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
test "should move friendly_id error to name" do
|
|
34
|
-
with_instance_of(model_class) do |record|
|
|
35
|
-
record.errors.add :name, "xxx"
|
|
36
|
-
record.errors.add :friendly_id, "yyy"
|
|
37
|
-
record.move_friendly_id_error_to_name
|
|
38
|
-
assert record.errors[:name].present? && record.errors[:friendly_id].blank?
|
|
39
|
-
assert_equal 2, record.errors.count
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
test "should reject reserved candidates" do
|
|
44
|
-
transaction do
|
|
45
|
-
record = model_class.new(name: "new")
|
|
46
|
-
def record.slug_candidates
|
|
47
|
-
[:name, "foo"]
|
|
48
|
-
end
|
|
49
|
-
record.save!
|
|
50
|
-
assert_equal "foo", record.friendly_id
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
test "should be invalid if all candidates are reserved" do
|
|
55
|
-
transaction do
|
|
56
|
-
record = model_class.new(name: "new")
|
|
57
|
-
def record.slug_candidates
|
|
58
|
-
["edit", "new"]
|
|
59
|
-
end
|
|
60
|
-
assert_raises(ActiveRecord::RecordInvalid) { record.save! }
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
test "should optionally treat reserved words as conflict" do
|
|
65
|
-
klass = Class.new(model_class) do
|
|
66
|
-
friendly_id :slug_candidates, use: [:slugged, :reserved], reserved_words: %w[new edit], treat_reserved_as_conflict: true
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
with_instance_of(klass, name: "new") do |record|
|
|
70
|
-
assert_match(/new-([0-9a-z]+-){4}[0-9a-z]+\z/, record.slug)
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
end
|
data/test/schema.rb
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
require "friendly_id/migration"
|
|
2
|
-
|
|
3
|
-
module FriendlyId
|
|
4
|
-
module Test
|
|
5
|
-
migration_class =
|
|
6
|
-
if ActiveRecord::VERSION::MAJOR >= 5
|
|
7
|
-
ActiveRecord::Migration[4.2]
|
|
8
|
-
else
|
|
9
|
-
ActiveRecord::Migration
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
class Schema < migration_class
|
|
13
|
-
class << self
|
|
14
|
-
def down
|
|
15
|
-
CreateFriendlyIdSlugs.down
|
|
16
|
-
tables.each do |name|
|
|
17
|
-
drop_table name
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def up
|
|
22
|
-
# TODO: use schema version to avoid ugly hacks like this
|
|
23
|
-
return if @done
|
|
24
|
-
CreateFriendlyIdSlugs.migrate :up
|
|
25
|
-
|
|
26
|
-
tables.each do |table_name|
|
|
27
|
-
create_table table_name do |t|
|
|
28
|
-
t.string :name
|
|
29
|
-
t.boolean :active
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
tables_with_uuid_primary_key.each do |table_name|
|
|
34
|
-
create_table table_name, primary_key: :uuid_key, id: false do |t|
|
|
35
|
-
t.string :name
|
|
36
|
-
t.string :uuid_key, null: false
|
|
37
|
-
t.string :slug
|
|
38
|
-
end
|
|
39
|
-
add_index table_name, :slug, unique: true
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
slugged_tables.each do |table_name|
|
|
43
|
-
add_column table_name, :slug, :string
|
|
44
|
-
add_index table_name, :slug, unique: true if table_name != "novels"
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
scoped_tables.each do |table_name|
|
|
48
|
-
add_column table_name, :slug, :string
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
paranoid_tables.each do |table_name|
|
|
52
|
-
add_column table_name, :slug, :string
|
|
53
|
-
add_column table_name, :deleted_at, :datetime
|
|
54
|
-
add_index table_name, :deleted_at
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# This will be used to test scopes
|
|
58
|
-
add_column :novels, :novelist_id, :integer
|
|
59
|
-
add_column :novels, :publisher_id, :integer
|
|
60
|
-
add_index :novels, [:slug, :publisher_id, :novelist_id], unique: true
|
|
61
|
-
|
|
62
|
-
# This will be used to test column name quoting
|
|
63
|
-
add_column :journalists, "strange name", :string
|
|
64
|
-
|
|
65
|
-
# This will be used to test STI
|
|
66
|
-
add_column :journalists, "type", :string
|
|
67
|
-
|
|
68
|
-
# These will be used to test i18n
|
|
69
|
-
add_column :journalists, "slug_en", :string
|
|
70
|
-
add_column :journalists, "slug_es", :string
|
|
71
|
-
add_column :journalists, "slug_de", :string
|
|
72
|
-
add_column :journalists, "slug_fr_ca", :string
|
|
73
|
-
|
|
74
|
-
# This will be used to test relationships
|
|
75
|
-
add_column :books, :author_id, :integer
|
|
76
|
-
|
|
77
|
-
# Used to test :scoped and :history together
|
|
78
|
-
add_column :restaurants, :city_id, :integer
|
|
79
|
-
|
|
80
|
-
# Used to test candidates
|
|
81
|
-
add_column :cities, :code, :string, limit: 3
|
|
82
|
-
|
|
83
|
-
# Used as a non-default slug_column
|
|
84
|
-
add_column :authors, :subdomain, :string
|
|
85
|
-
|
|
86
|
-
@done = true
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
private
|
|
90
|
-
|
|
91
|
-
def slugged_tables
|
|
92
|
-
%w[journalists articles novelists novels manuals cities]
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def paranoid_tables
|
|
96
|
-
["paranoid_records"]
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
def tables_with_uuid_primary_key
|
|
100
|
-
["menu_items"]
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def scoped_tables
|
|
104
|
-
["restaurants"]
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def simple_tables
|
|
108
|
-
%w[authors books publishers]
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def tables
|
|
112
|
-
simple_tables + slugged_tables + scoped_tables + paranoid_tables
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
end
|
data/test/scoped_test.rb
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
require "helper"
|
|
2
|
-
|
|
3
|
-
class Novelist < ActiveRecord::Base
|
|
4
|
-
extend FriendlyId
|
|
5
|
-
friendly_id :name, use: :slugged
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
class Novel < ActiveRecord::Base
|
|
9
|
-
extend FriendlyId
|
|
10
|
-
belongs_to :novelist
|
|
11
|
-
belongs_to :publisher
|
|
12
|
-
friendly_id :name, use: :scoped, scope: [:publisher, :novelist]
|
|
13
|
-
|
|
14
|
-
def should_generate_new_friendly_id?
|
|
15
|
-
new_record? || super
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
class Publisher < ActiveRecord::Base
|
|
20
|
-
has_many :novels
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
class ScopedTest < TestCaseClass
|
|
24
|
-
include FriendlyId::Test
|
|
25
|
-
include FriendlyId::Test::Shared::Core
|
|
26
|
-
|
|
27
|
-
def model_class
|
|
28
|
-
Novel
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
test "should detect scope column from belongs_to relation" do
|
|
32
|
-
assert_equal ["publisher_id", "novelist_id"], Novel.friendly_id_config.scope_columns
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
test "should detect scope column from explicit column name" do
|
|
36
|
-
model_class = Class.new(ActiveRecord::Base) do
|
|
37
|
-
self.abstract_class = true
|
|
38
|
-
extend FriendlyId
|
|
39
|
-
friendly_id :empty, use: :scoped, scope: :dummy
|
|
40
|
-
end
|
|
41
|
-
assert_equal ["dummy"], model_class.friendly_id_config.scope_columns
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
test "should allow duplicate slugs outside scope" do
|
|
45
|
-
transaction do
|
|
46
|
-
novel1 = Novel.create! name: "a", novelist: Novelist.create!(name: "a")
|
|
47
|
-
novel2 = Novel.create! name: "a", novelist: Novelist.create!(name: "b")
|
|
48
|
-
assert_equal novel1.friendly_id, novel2.friendly_id
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
test "should not allow duplicate slugs inside scope" do
|
|
53
|
-
with_instance_of Novelist do |novelist|
|
|
54
|
-
novel1 = Novel.create! name: "a", novelist: novelist
|
|
55
|
-
novel2 = Novel.create! name: "a", novelist: novelist
|
|
56
|
-
assert novel1.friendly_id != novel2.friendly_id
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
test "should apply scope with multiple columns" do
|
|
61
|
-
transaction do
|
|
62
|
-
novelist = Novelist.create! name: "a"
|
|
63
|
-
publisher = Publisher.create! name: "b"
|
|
64
|
-
novel1 = Novel.create! name: "c", novelist: novelist, publisher: publisher
|
|
65
|
-
novel2 = Novel.create! name: "c", novelist: novelist, publisher: Publisher.create(name: "d")
|
|
66
|
-
novel3 = Novel.create! name: "c", novelist: Novelist.create(name: "e"), publisher: publisher
|
|
67
|
-
novel4 = Novel.create! name: "c", novelist: novelist, publisher: publisher
|
|
68
|
-
assert_equal novel1.friendly_id, novel2.friendly_id
|
|
69
|
-
assert_equal novel2.friendly_id, novel3.friendly_id
|
|
70
|
-
assert novel3.friendly_id != novel4.friendly_id
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
test "should allow a record to reuse its own slug" do
|
|
75
|
-
with_instance_of(model_class) do |record|
|
|
76
|
-
old_id = record.friendly_id
|
|
77
|
-
record.slug = nil
|
|
78
|
-
record.save!
|
|
79
|
-
assert_equal old_id, record.friendly_id
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
test "should generate new slug when scope changes" do
|
|
84
|
-
transaction do
|
|
85
|
-
novelist = Novelist.create! name: "a"
|
|
86
|
-
publisher = Publisher.create! name: "b"
|
|
87
|
-
novel1 = Novel.create! name: "c", novelist: novelist, publisher: publisher
|
|
88
|
-
novel2 = Novel.create! name: "c", novelist: novelist, publisher: Publisher.create(name: "d")
|
|
89
|
-
assert_equal novel1.friendly_id, novel2.friendly_id
|
|
90
|
-
novel2.publisher = publisher
|
|
91
|
-
novel2.save!
|
|
92
|
-
assert novel2.friendly_id != novel1.friendly_id
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
end
|
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
require "helper"
|
|
2
|
-
|
|
3
|
-
class Article < ActiveRecord::Base
|
|
4
|
-
extend FriendlyId
|
|
5
|
-
friendly_id :name, use: :sequentially_slugged
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
class SequentiallySluggedTest < TestCaseClass
|
|
9
|
-
include FriendlyId::Test
|
|
10
|
-
include FriendlyId::Test::Shared::Core
|
|
11
|
-
|
|
12
|
-
def model_class
|
|
13
|
-
Article
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
test "should generate numerically sequential slugs" do
|
|
17
|
-
transaction do
|
|
18
|
-
records = 12.times.map { model_class.create! name: "Some news" }
|
|
19
|
-
assert_equal "some-news", records[0].slug
|
|
20
|
-
(1...12).each { |i| assert_equal "some-news-#{i + 1}", records[i].slug }
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
test "should cope when slugs are missing from the sequence" do
|
|
25
|
-
transaction do
|
|
26
|
-
record_1 = model_class.create!(name: "A thing")
|
|
27
|
-
record_2 = model_class.create!(name: "A thing")
|
|
28
|
-
record_3 = model_class.create!(name: "A thing")
|
|
29
|
-
|
|
30
|
-
assert_equal "a-thing", record_1.slug
|
|
31
|
-
assert_equal "a-thing-2", record_2.slug
|
|
32
|
-
assert_equal "a-thing-3", record_3.slug
|
|
33
|
-
|
|
34
|
-
record_2.destroy
|
|
35
|
-
|
|
36
|
-
record_4 = model_class.create!(name: "A thing")
|
|
37
|
-
|
|
38
|
-
assert_equal "a-thing-4", record_4.slug
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
test "should cope with strange column names" do
|
|
43
|
-
model_class = Class.new(ActiveRecord::Base) do
|
|
44
|
-
self.table_name = "journalists"
|
|
45
|
-
extend FriendlyId
|
|
46
|
-
friendly_id :name, use: :sequentially_slugged, slug_column: "strange name"
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
transaction do
|
|
50
|
-
record_1 = model_class.create! name: "Lois Lane"
|
|
51
|
-
record_2 = model_class.create! name: "Lois Lane"
|
|
52
|
-
|
|
53
|
-
assert_equal "lois-lane", record_1.attributes["strange name"]
|
|
54
|
-
assert_equal "lois-lane-2", record_2.attributes["strange name"]
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
test "should correctly sequence slugs that end in a number" do
|
|
59
|
-
transaction do
|
|
60
|
-
record1 = model_class.create! name: "Peugeuot 206"
|
|
61
|
-
assert_equal "peugeuot-206", record1.slug
|
|
62
|
-
record2 = model_class.create! name: "Peugeuot 206"
|
|
63
|
-
assert_equal "peugeuot-206-2", record2.slug
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
test "should correctly sequence slugs that begin with a number" do
|
|
68
|
-
transaction do
|
|
69
|
-
record1 = model_class.create! name: "2010 to 2015 Records"
|
|
70
|
-
assert_equal "2010-to-2015-records", record1.slug
|
|
71
|
-
record2 = model_class.create! name: "2010 to 2015 Records"
|
|
72
|
-
assert_equal "2010-to-2015-records-2", record2.slug
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
test "should sequence with a custom sequence separator" do
|
|
77
|
-
model_class = Class.new(ActiveRecord::Base) do
|
|
78
|
-
self.table_name = "novelists"
|
|
79
|
-
extend FriendlyId
|
|
80
|
-
friendly_id :name, use: :sequentially_slugged, sequence_separator: ":"
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
transaction do
|
|
84
|
-
record_1 = model_class.create! name: "Julian Barnes"
|
|
85
|
-
record_2 = model_class.create! name: "Julian Barnes"
|
|
86
|
-
|
|
87
|
-
assert_equal "julian-barnes", record_1.slug
|
|
88
|
-
assert_equal "julian-barnes:2", record_2.slug
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
test "should not generate a slug when canidates set is empty" do
|
|
93
|
-
model_class = Class.new(ActiveRecord::Base) do
|
|
94
|
-
self.table_name = "cities"
|
|
95
|
-
extend FriendlyId
|
|
96
|
-
friendly_id :slug_candidates, use: [:sequentially_slugged]
|
|
97
|
-
|
|
98
|
-
def slug_candidates
|
|
99
|
-
[name, [name, code]]
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
transaction do
|
|
103
|
-
record = model_class.create!(name: nil, code: nil)
|
|
104
|
-
assert_nil record.slug
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
test "should not generate a slug when the sluggable attribute is blank" do
|
|
109
|
-
record = model_class.create!(name: "")
|
|
110
|
-
assert_nil record.slug
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
class SequentiallySluggedTestWithHistory < TestCaseClass
|
|
115
|
-
include FriendlyId::Test
|
|
116
|
-
include FriendlyId::Test::Shared::Core
|
|
117
|
-
|
|
118
|
-
class Article < ActiveRecord::Base
|
|
119
|
-
extend FriendlyId
|
|
120
|
-
friendly_id :name, use: [:sequentially_slugged, :history]
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
Journalist = Class.new(ActiveRecord::Base) do
|
|
124
|
-
extend FriendlyId
|
|
125
|
-
friendly_id :name, use: [:sequentially_slugged, :history], slug_column: "strange name"
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
def model_class
|
|
129
|
-
Article
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
test "should work with regeneration with history when slug already exists" do
|
|
133
|
-
transaction do
|
|
134
|
-
record1 = model_class.create! name: "Test name"
|
|
135
|
-
record2 = model_class.create! name: "Another test name"
|
|
136
|
-
assert_equal "test-name", record1.slug
|
|
137
|
-
assert_equal "another-test-name", record2.slug
|
|
138
|
-
|
|
139
|
-
record2.name = "Test name"
|
|
140
|
-
record2.slug = nil
|
|
141
|
-
record2.save!
|
|
142
|
-
assert_equal "test-name-2", record2.slug
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
test "should work with regeneration with history when 2 slugs already exists and the second is changed" do
|
|
147
|
-
transaction do
|
|
148
|
-
record1 = model_class.create! name: "Test name"
|
|
149
|
-
record2 = model_class.create! name: "Test name"
|
|
150
|
-
record3 = model_class.create! name: "Another test name"
|
|
151
|
-
assert_equal "test-name", record1.slug
|
|
152
|
-
assert_equal "test-name-2", record2.slug
|
|
153
|
-
assert_equal "another-test-name", record3.slug
|
|
154
|
-
|
|
155
|
-
record2.name = "One more test name"
|
|
156
|
-
record2.slug = nil
|
|
157
|
-
record2.save!
|
|
158
|
-
assert_equal "one-more-test-name", record2.slug
|
|
159
|
-
|
|
160
|
-
record3.name = "Test name"
|
|
161
|
-
record3.slug = nil
|
|
162
|
-
record3.save!
|
|
163
|
-
assert_equal "test-name-3", record3.slug
|
|
164
|
-
end
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
test "should cope with strange column names" do
|
|
168
|
-
transaction do
|
|
169
|
-
record_1 = Journalist.create! name: "Lois Lane"
|
|
170
|
-
record_2 = Journalist.create! name: "Lois Lane"
|
|
171
|
-
|
|
172
|
-
assert_equal "lois-lane", record_1.attributes["strange name"]
|
|
173
|
-
assert_equal "lois-lane-2", record_2.attributes["strange name"]
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
end
|
|
177
|
-
|
|
178
|
-
class City < ActiveRecord::Base
|
|
179
|
-
has_many :restaurants
|
|
180
|
-
end
|
|
181
|
-
|
|
182
|
-
class Restaurant < ActiveRecord::Base
|
|
183
|
-
extend FriendlyId
|
|
184
|
-
belongs_to :city
|
|
185
|
-
friendly_id :name, use: [:sequentially_slugged, :scoped, :history], scope: :city
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
class SequentiallySluggedTestWithScopedHistory < TestCaseClass
|
|
189
|
-
include FriendlyId::Test
|
|
190
|
-
include FriendlyId::Test::Shared::Core
|
|
191
|
-
|
|
192
|
-
def model_class
|
|
193
|
-
Restaurant
|
|
194
|
-
end
|
|
195
|
-
|
|
196
|
-
test "should work with regeneration with scoped history" do
|
|
197
|
-
transaction do
|
|
198
|
-
city1 = City.create!
|
|
199
|
-
City.create!
|
|
200
|
-
record1 = model_class.create! name: "Test name", city: city1
|
|
201
|
-
record2 = model_class.create! name: "Test name", city: city1
|
|
202
|
-
|
|
203
|
-
assert_equal "test-name", record1.slug
|
|
204
|
-
assert_equal "test-name-2", record2.slug
|
|
205
|
-
|
|
206
|
-
record2.name = "Another test name"
|
|
207
|
-
record2.slug = nil
|
|
208
|
-
record2.save!
|
|
209
|
-
|
|
210
|
-
record3 = model_class.create! name: "Test name", city: city1
|
|
211
|
-
assert_equal "test-name-3", record3.slug
|
|
212
|
-
end
|
|
213
|
-
end
|
|
214
|
-
end
|
data/test/shared.rb
DELETED
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
module FriendlyId
|
|
2
|
-
module Test
|
|
3
|
-
module Shared
|
|
4
|
-
module Slugged
|
|
5
|
-
test "configuration should have a sequence_separator" do
|
|
6
|
-
assert !model_class.friendly_id_config.sequence_separator.empty?
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
test "should make a new slug if the slug has been set to nil changed" do
|
|
10
|
-
with_instance_of model_class do |record|
|
|
11
|
-
record.name = "Changed Value"
|
|
12
|
-
record.slug = nil
|
|
13
|
-
record.save!
|
|
14
|
-
assert_equal "changed-value", record.slug
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
test "should add a UUID for duplicate friendly ids" do
|
|
19
|
-
with_instance_of model_class do |record|
|
|
20
|
-
record2 = model_class.create! name: record.name
|
|
21
|
-
assert record2.friendly_id.match(/([0-9a-z]+-){4}[0-9a-z]+\z/)
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
test "should not add slug sequence on update after other conflicting slugs were added" do
|
|
26
|
-
with_instance_of model_class do |record|
|
|
27
|
-
old = record.friendly_id
|
|
28
|
-
model_class.create! name: record.name
|
|
29
|
-
record.save!
|
|
30
|
-
record.reload
|
|
31
|
-
assert_equal old, record.to_param
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
test "should not change the sequence on save" do
|
|
36
|
-
with_instance_of model_class do |record|
|
|
37
|
-
record2 = model_class.create! name: record.name
|
|
38
|
-
friendly_id = record2.friendly_id
|
|
39
|
-
record2.active = !record2.active
|
|
40
|
-
record2.save!
|
|
41
|
-
assert_equal friendly_id, record2.reload.friendly_id
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
test "should create slug on save if the slug is nil" do
|
|
46
|
-
with_instance_of model_class do |record|
|
|
47
|
-
record.slug = nil
|
|
48
|
-
record.save!
|
|
49
|
-
refute_nil record.slug
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
test "should set the slug to nil on dup" do
|
|
54
|
-
with_instance_of model_class do |record|
|
|
55
|
-
record2 = record.dup
|
|
56
|
-
assert_nil record2.slug
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
test "when validations block save, to_param should return friendly_id rather than nil" do
|
|
61
|
-
my_model_class = Class.new(model_class)
|
|
62
|
-
self.class.const_set("Foo", my_model_class)
|
|
63
|
-
with_instance_of my_model_class do |record|
|
|
64
|
-
record.update my_model_class.friendly_id_config.slug_column => nil
|
|
65
|
-
record = my_model_class.friendly.find(record.id)
|
|
66
|
-
record.class.validate proc { errors.add(:name, "FAIL") }
|
|
67
|
-
record.save
|
|
68
|
-
assert_equal record.to_param, record.friendly_id
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
module Core
|
|
74
|
-
test "finds should respect conditions" do
|
|
75
|
-
with_instance_of(model_class) do |record|
|
|
76
|
-
assert_raises(ActiveRecord::RecordNotFound) do
|
|
77
|
-
model_class.where("1 = 2").friendly.find record.friendly_id
|
|
78
|
-
end
|
|
79
|
-
assert_raises(ActiveRecord::RecordNotFound) do
|
|
80
|
-
model_class.where("1 = 2").friendly.find record.id
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
test "should be findable by friendly id" do
|
|
86
|
-
with_instance_of(model_class) { |record| assert model_class.friendly.find record.friendly_id }
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
test "should exist? by friendly id" do
|
|
90
|
-
with_instance_of(model_class) do |record|
|
|
91
|
-
assert model_class.friendly.exists? record.id
|
|
92
|
-
assert model_class.friendly.exists? record.id.to_s
|
|
93
|
-
assert model_class.friendly.exists? record.friendly_id
|
|
94
|
-
assert model_class.friendly.exists?({id: record.id})
|
|
95
|
-
assert model_class.friendly.exists?(["id = ?", record.id])
|
|
96
|
-
assert !model_class.friendly.exists?(record.friendly_id + "-hello")
|
|
97
|
-
assert !model_class.friendly.exists?(0)
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
test "should be findable by id as integer" do
|
|
102
|
-
with_instance_of(model_class) { |record| assert model_class.friendly.find record.id.to_i }
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
test "should be findable by id as string" do
|
|
106
|
-
with_instance_of(model_class) { |record| assert model_class.friendly.find record.id.to_s }
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
test "should treat numeric part of string as an integer id" do
|
|
110
|
-
with_instance_of(model_class) do |record|
|
|
111
|
-
assert_raises(ActiveRecord::RecordNotFound) do
|
|
112
|
-
model_class.friendly.find "#{record.id}-foo"
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
test "should be findable by numeric friendly_id" do
|
|
118
|
-
with_instance_of(model_class, name: "206") { |record| assert model_class.friendly.find record.friendly_id }
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
test "to_param should return the friendly_id" do
|
|
122
|
-
with_instance_of(model_class) { |record| assert_equal record.friendly_id, record.to_param }
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
if ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR < 2
|
|
126
|
-
test "should be findable by themselves" do
|
|
127
|
-
with_instance_of(model_class) { |record| assert_equal record, model_class.friendly.find(record) }
|
|
128
|
-
end
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
test "updating record's other values should not change the friendly_id" do
|
|
132
|
-
with_instance_of model_class do |record|
|
|
133
|
-
old = record.friendly_id
|
|
134
|
-
record.update! active: false
|
|
135
|
-
assert model_class.friendly.find old
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
test "instances found by a single id should not be read-only" do
|
|
140
|
-
with_instance_of(model_class) { |record| assert !model_class.friendly.find(record.friendly_id).readonly? }
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
test "failing finds with unfriendly_id should raise errors normally" do
|
|
144
|
-
assert_raises(ActiveRecord::RecordNotFound) { model_class.friendly.find 0 }
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
test "should return numeric id if the friendly_id is nil" do
|
|
148
|
-
with_instance_of(model_class) do |record|
|
|
149
|
-
record.expects(:friendly_id).returns(nil)
|
|
150
|
-
assert_equal record.id.to_s, record.to_param
|
|
151
|
-
end
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
test "should return numeric id if the friendly_id is an empty string" do
|
|
155
|
-
with_instance_of(model_class) do |record|
|
|
156
|
-
record.expects(:friendly_id).returns("")
|
|
157
|
-
assert_equal record.id.to_s, record.to_param
|
|
158
|
-
end
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
test "should return the friendly_id as a string" do
|
|
162
|
-
with_instance_of(model_class) do |record|
|
|
163
|
-
record.expects(:friendly_id).returns(5)
|
|
164
|
-
assert_equal "5", record.to_param
|
|
165
|
-
end
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
test "should return numeric id if the friendly_id is blank" do
|
|
169
|
-
with_instance_of(model_class) do |record|
|
|
170
|
-
record.expects(:friendly_id).returns(" ")
|
|
171
|
-
assert_equal record.id.to_s, record.to_param
|
|
172
|
-
end
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
test "should return nil for to_param with a new record" do
|
|
176
|
-
assert_nil model_class.new.to_param
|
|
177
|
-
end
|
|
178
|
-
end
|
|
179
|
-
end
|
|
180
|
-
end
|
|
181
|
-
end
|