acts-as-taggable-on 3.1.1 → 3.2.2
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/.gitignore +1 -1
- data/.travis.yml +9 -7
- data/Appraisals +13 -8
- data/CHANGELOG.md +27 -7
- data/Gemfile +1 -2
- data/README.md +36 -19
- data/Rakefile +5 -17
- data/UPGRADING.md +6 -0
- data/acts-as-taggable-on.gemspec +15 -15
- data/db/migrate/1_acts_as_taggable_on_migration.rb +3 -3
- data/db/migrate/2_add_missing_unique_indices.rb +3 -5
- data/db/migrate/3_add_taggings_counter_cache_to_tags.rb +1 -1
- data/gemfiles/activerecord_3.2.gemfile +15 -0
- data/gemfiles/activerecord_4.0.gemfile +15 -0
- data/gemfiles/activerecord_4.1.gemfile +15 -0
- data/gemfiles/activerecord_edge.gemfile +16 -0
- data/lib/acts-as-taggable-on.rb +23 -21
- data/lib/acts_as_taggable_on/acts_as_taggable_on/cache.rb +2 -4
- data/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb +29 -20
- data/lib/acts_as_taggable_on/acts_as_taggable_on/compatibility.rb +11 -10
- data/lib/acts_as_taggable_on/acts_as_taggable_on/core.rb +103 -85
- data/lib/acts_as_taggable_on/acts_as_taggable_on/ownership.rb +5 -12
- data/lib/acts_as_taggable_on/acts_as_taggable_on/related.rb +11 -11
- data/lib/acts_as_taggable_on/engine.rb +0 -1
- data/lib/acts_as_taggable_on/tag.rb +24 -19
- data/lib/acts_as_taggable_on/tag_list.rb +97 -22
- data/lib/acts_as_taggable_on/taggable.rb +26 -30
- data/lib/acts_as_taggable_on/tagger.rb +30 -18
- data/lib/acts_as_taggable_on/tagging.rb +7 -8
- data/lib/acts_as_taggable_on/tags_helper.rb +1 -1
- data/lib/acts_as_taggable_on/utils.rb +57 -35
- data/lib/acts_as_taggable_on/version.rb +1 -1
- data/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb +133 -138
- data/spec/acts_as_taggable_on/acts_as_tagger_spec.rb +55 -58
- data/spec/acts_as_taggable_on/caching_spec.rb +34 -35
- data/spec/acts_as_taggable_on/related_spec.rb +59 -113
- data/spec/acts_as_taggable_on/single_table_inheritance_spec.rb +118 -95
- data/spec/acts_as_taggable_on/tag_list_spec.rb +89 -57
- data/spec/acts_as_taggable_on/tag_spec.rb +129 -116
- data/spec/acts_as_taggable_on/taggable_spec.rb +539 -352
- data/spec/acts_as_taggable_on/tagger_spec.rb +81 -78
- data/spec/acts_as_taggable_on/tagging_spec.rb +13 -14
- data/spec/acts_as_taggable_on/tags_helper_spec.rb +25 -25
- data/spec/acts_as_taggable_on/utils_spec.rb +7 -13
- data/spec/internal/app/models/altered_inheriting_taggable_model.rb +3 -0
- data/spec/internal/app/models/cached_model.rb +3 -0
- data/spec/internal/app/models/cached_model_with_array.rb +5 -0
- data/spec/internal/app/models/company.rb +15 -0
- data/spec/internal/app/models/inheriting_taggable_model.rb +2 -0
- data/spec/internal/app/models/market.rb +2 -0
- data/spec/{models.rb → internal/app/models/models.rb} +34 -2
- data/spec/internal/app/models/non_standard_id_taggable_model.rb +8 -0
- data/spec/internal/app/models/ordered_taggable_model.rb +4 -0
- data/spec/internal/app/models/other_cached_model.rb +3 -0
- data/spec/internal/app/models/other_taggable_model.rb +4 -0
- data/spec/internal/app/models/student.rb +2 -0
- data/spec/internal/app/models/taggable_model.rb +13 -0
- data/spec/internal/app/models/untaggable_model.rb +3 -0
- data/spec/internal/app/models/user.rb +3 -0
- data/spec/{database.yml.sample → internal/config/database.yml.sample} +2 -2
- data/spec/internal/db/schema.rb +97 -0
- data/spec/schema.rb +11 -0
- data/spec/spec_helper.rb +9 -62
- data/spec/support/array.rb +9 -0
- data/spec/support/database.rb +42 -0
- data/spec/support/database_cleaner.rb +21 -0
- metadata +105 -43
- data/gemfiles/rails_3.2.gemfile +0 -7
- data/gemfiles/rails_4.0.gemfile +0 -7
- data/gemfiles/rails_4.1.gemfile +0 -7
- data/gemfiles/rails_edge.gemfile +0 -7
- data/spec/bm.rb +0 -52
|
@@ -2,124 +2,156 @@
|
|
|
2
2
|
require 'spec_helper'
|
|
3
3
|
|
|
4
4
|
describe ActsAsTaggableOn::TagList do
|
|
5
|
-
let(:tag_list) { ActsAsTaggableOn::TagList.new(
|
|
5
|
+
let(:tag_list) { ActsAsTaggableOn::TagList.new('awesome', 'radical') }
|
|
6
|
+
let(:another_tag_list) { ActsAsTaggableOn::TagList.new('awesome','crazy', 'alien') }
|
|
6
7
|
|
|
7
8
|
it { should be_kind_of Array }
|
|
8
9
|
|
|
9
|
-
it
|
|
10
|
-
ActsAsTaggableOn::TagList.from([]).
|
|
10
|
+
it '#from should return empty array if empty array is passed' do
|
|
11
|
+
expect(ActsAsTaggableOn::TagList.from([])).to be_empty
|
|
11
12
|
end
|
|
12
13
|
|
|
13
|
-
describe
|
|
14
|
-
it
|
|
15
|
-
tag_list.add(
|
|
16
|
-
tag_list.include?(
|
|
14
|
+
describe '#add' do
|
|
15
|
+
it 'should be able to be add a new tag word' do
|
|
16
|
+
tag_list.add('cool')
|
|
17
|
+
expect(tag_list.include?('cool')).to be_truthy
|
|
17
18
|
end
|
|
18
19
|
|
|
19
|
-
it
|
|
20
|
-
tag_list.add(
|
|
21
|
-
tag_list.
|
|
20
|
+
it 'should be able to add delimited lists of words' do
|
|
21
|
+
tag_list.add('cool, wicked', parse: true)
|
|
22
|
+
expect(tag_list).to include('cool', 'wicked')
|
|
22
23
|
end
|
|
23
24
|
|
|
24
|
-
it
|
|
25
|
-
tag_list.add("'cool, wicked', \"really cool, really wicked\"", :
|
|
26
|
-
tag_list.
|
|
25
|
+
it 'should be able to add delimited list of words with quoted delimiters' do
|
|
26
|
+
tag_list.add("'cool, wicked', \"really cool, really wicked\"", parse: true)
|
|
27
|
+
expect(tag_list).to include('cool, wicked', 'really cool, really wicked')
|
|
27
28
|
end
|
|
28
29
|
|
|
29
|
-
it
|
|
30
|
-
tag_list.add("john's cool car, mary's wicked toy", :
|
|
31
|
-
tag_list.
|
|
30
|
+
it 'should be able to handle other uses of quotation marks correctly' do
|
|
31
|
+
tag_list.add("john's cool car, mary's wicked toy", parse: true)
|
|
32
|
+
expect(tag_list).to include("john's cool car", "mary's wicked toy")
|
|
32
33
|
end
|
|
33
34
|
|
|
34
|
-
it
|
|
35
|
-
tag_list.add(
|
|
36
|
-
tag_list.
|
|
35
|
+
it 'should be able to add an array of words' do
|
|
36
|
+
tag_list.add(%w(cool wicked), parse: true)
|
|
37
|
+
expect(tag_list).to include('cool', 'wicked')
|
|
37
38
|
end
|
|
38
39
|
|
|
39
|
-
it
|
|
40
|
-
tag_list.add(
|
|
41
|
-
tag_list.to_s.
|
|
40
|
+
it 'should quote escape tags with commas in them' do
|
|
41
|
+
tag_list.add('cool', 'rad,bodacious')
|
|
42
|
+
expect(tag_list.to_s).to eq("awesome, radical, cool, \"rad,bodacious\"")
|
|
42
43
|
end
|
|
43
44
|
|
|
44
45
|
end
|
|
45
46
|
|
|
46
|
-
describe
|
|
47
|
-
it
|
|
48
|
-
tag_list.remove(
|
|
49
|
-
tag_list.
|
|
47
|
+
describe '#remove' do
|
|
48
|
+
it 'should be able to remove words' do
|
|
49
|
+
tag_list.remove('awesome')
|
|
50
|
+
expect(tag_list).to_not include('awesome')
|
|
50
51
|
end
|
|
51
52
|
|
|
52
|
-
it
|
|
53
|
-
tag_list.remove(
|
|
54
|
-
tag_list.
|
|
53
|
+
it 'should be able to remove delimited lists of words' do
|
|
54
|
+
tag_list.remove('awesome, radical', parse: true)
|
|
55
|
+
expect(tag_list).to be_empty
|
|
55
56
|
end
|
|
56
57
|
|
|
57
|
-
it
|
|
58
|
-
tag_list.remove(
|
|
59
|
-
tag_list.
|
|
58
|
+
it 'should be able to remove an array of words' do
|
|
59
|
+
tag_list.remove(%w(awesome radical), parse: true)
|
|
60
|
+
expect(tag_list).to be_empty
|
|
60
61
|
end
|
|
61
62
|
end
|
|
62
63
|
|
|
63
|
-
describe
|
|
64
|
-
it
|
|
65
|
-
tag_list
|
|
64
|
+
describe '#+' do
|
|
65
|
+
it 'should not have duplicate tags' do
|
|
66
|
+
new_tag_list = tag_list + another_tag_list
|
|
67
|
+
expect(tag_list).to eq(%w[awesome radical])
|
|
68
|
+
expect(another_tag_list).to eq(%w[awesome crazy alien])
|
|
69
|
+
expect(new_tag_list).to eq(%w[awesome radical crazy alien])
|
|
66
70
|
end
|
|
67
71
|
|
|
68
|
-
it
|
|
72
|
+
it 'should have class : ActsAsTaggableOn::TagList' do
|
|
73
|
+
new_tag_list = tag_list + another_tag_list
|
|
74
|
+
expect(new_tag_list.class).to eq(ActsAsTaggableOn::TagList)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
describe '#concat' do
|
|
79
|
+
it 'should not have duplicate tags' do
|
|
80
|
+
expect(tag_list.concat(another_tag_list)).to eq(%w[awesome radical crazy alien])
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it 'should have class : ActsAsTaggableOn::TagList' do
|
|
84
|
+
new_tag_list = tag_list.concat(another_tag_list)
|
|
85
|
+
expect(new_tag_list.class).to eq(ActsAsTaggableOn::TagList)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
describe '#to_s' do
|
|
90
|
+
it 'should give a delimited list of words when converted to string' do
|
|
91
|
+
expect(tag_list.to_s).to eq('awesome, radical')
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it 'should be able to call to_s on a frozen tag list' do
|
|
69
95
|
tag_list.freeze
|
|
70
|
-
|
|
71
|
-
|
|
96
|
+
expect(-> { tag_list.add('cool', 'rad,bodacious') }).to raise_error
|
|
97
|
+
expect(-> { tag_list.to_s }).to_not raise_error
|
|
72
98
|
end
|
|
73
99
|
end
|
|
74
100
|
|
|
75
|
-
describe
|
|
76
|
-
it
|
|
101
|
+
describe 'cleaning' do
|
|
102
|
+
it 'should parameterize if force_parameterize is set to true' do
|
|
77
103
|
ActsAsTaggableOn.force_parameterize = true
|
|
78
|
-
tag_list = ActsAsTaggableOn::TagList.new(
|
|
104
|
+
tag_list = ActsAsTaggableOn::TagList.new('awesome()', 'radical)(cc')
|
|
79
105
|
|
|
80
|
-
tag_list.to_s.
|
|
106
|
+
expect(tag_list.to_s).to eq('awesome, radical-cc')
|
|
81
107
|
ActsAsTaggableOn.force_parameterize = false
|
|
82
108
|
end
|
|
83
109
|
|
|
84
|
-
it
|
|
110
|
+
it 'should lowercase if force_lowercase is set to true' do
|
|
85
111
|
ActsAsTaggableOn.force_lowercase = true
|
|
86
112
|
|
|
87
|
-
tag_list = ActsAsTaggableOn::TagList.new(
|
|
88
|
-
tag_list.to_s.
|
|
113
|
+
tag_list = ActsAsTaggableOn::TagList.new('aweSomE', 'RaDicaL', 'Entrée')
|
|
114
|
+
expect(tag_list.to_s).to eq('awesome, radical, entrée')
|
|
89
115
|
|
|
90
116
|
ActsAsTaggableOn.force_lowercase = false
|
|
91
117
|
end
|
|
92
118
|
|
|
93
119
|
end
|
|
94
120
|
|
|
95
|
-
describe
|
|
96
|
-
before do
|
|
121
|
+
describe 'Multiple Delimiter' do
|
|
122
|
+
before do
|
|
97
123
|
@old_delimiter = ActsAsTaggableOn.delimiter
|
|
98
124
|
end
|
|
99
125
|
|
|
100
|
-
after do
|
|
126
|
+
after do
|
|
101
127
|
ActsAsTaggableOn.delimiter = @old_delimiter
|
|
102
128
|
end
|
|
103
129
|
|
|
104
|
-
it
|
|
130
|
+
it 'should separate tags by delimiters' do
|
|
105
131
|
ActsAsTaggableOn.delimiter = [',', ' ', '\|']
|
|
106
|
-
tag_list = ActsAsTaggableOn::TagList.from
|
|
107
|
-
tag_list.to_s.
|
|
132
|
+
tag_list = ActsAsTaggableOn::TagList.from 'cool, data|I have'
|
|
133
|
+
expect(tag_list.to_s).to eq('cool, data, I, have')
|
|
108
134
|
end
|
|
109
135
|
|
|
110
|
-
it
|
|
136
|
+
it 'should escape quote' do
|
|
111
137
|
ActsAsTaggableOn.delimiter = [',', ' ', '\|']
|
|
112
138
|
tag_list = ActsAsTaggableOn::TagList.from "'I have'|cool, data"
|
|
113
|
-
tag_list.to_s.
|
|
139
|
+
expect(tag_list.to_s).to eq('"I have", cool, data')
|
|
114
140
|
|
|
115
141
|
tag_list = ActsAsTaggableOn::TagList.from '"I, have"|cool, data'
|
|
116
|
-
tag_list.to_s.
|
|
142
|
+
expect(tag_list.to_s).to eq('"I, have", cool, data')
|
|
117
143
|
end
|
|
118
144
|
|
|
119
|
-
it
|
|
145
|
+
it 'should work for utf8 delimiter and long delimiter' do
|
|
120
146
|
ActsAsTaggableOn.delimiter = [',', '的', '可能是']
|
|
121
|
-
tag_list = ActsAsTaggableOn::TagList.from
|
|
122
|
-
tag_list.to_s.
|
|
147
|
+
tag_list = ActsAsTaggableOn::TagList.from '我的东西可能是不见了,还好有备份'
|
|
148
|
+
expect(tag_list.to_s).to eq('我, 东西, 不见了, 还好有备份')
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it 'should work for multiple quoted tags' do
|
|
152
|
+
ActsAsTaggableOn.delimiter = [',']
|
|
153
|
+
tag_list = ActsAsTaggableOn::TagList.from '"Ruby Monsters","eat Katzenzungen"'
|
|
154
|
+
expect(tag_list.to_s).to eq('Ruby Monsters, eat Katzenzungen')
|
|
123
155
|
end
|
|
124
156
|
end
|
|
125
157
|
|
|
@@ -3,207 +3,219 @@ require 'spec_helper'
|
|
|
3
3
|
require 'db/migrate/2_add_missing_unique_indices.rb'
|
|
4
4
|
|
|
5
5
|
shared_examples_for 'without unique index' do
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
prepend_before(:all) { AddMissingUniqueIndices.down }
|
|
7
|
+
append_after(:all) do
|
|
8
|
+
ActsAsTaggableOn::Tag.delete_all
|
|
9
|
+
AddMissingUniqueIndices.up
|
|
10
|
+
end
|
|
8
11
|
end
|
|
9
12
|
|
|
10
13
|
describe ActsAsTaggableOn::Tag do
|
|
11
14
|
before(:each) do
|
|
12
|
-
clean_database!
|
|
13
15
|
@tag = ActsAsTaggableOn::Tag.new
|
|
14
|
-
@user = TaggableModel.create(:
|
|
16
|
+
@user = TaggableModel.create(name: 'Pablo')
|
|
15
17
|
end
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
|
|
20
|
+
describe 'named like any' do
|
|
21
|
+
if ActsAsTaggableOn::Utils.using_case_insensitive_collation?
|
|
22
|
+
context 'case insensitive collation and unique index on tag name' do
|
|
20
23
|
before(:each) do
|
|
21
|
-
ActsAsTaggableOn::Tag.create(:
|
|
22
|
-
ActsAsTaggableOn::Tag.create(:
|
|
24
|
+
ActsAsTaggableOn::Tag.create(name: 'Awesome')
|
|
25
|
+
ActsAsTaggableOn::Tag.create(name: 'epic')
|
|
23
26
|
end
|
|
24
27
|
|
|
25
|
-
it
|
|
26
|
-
ActsAsTaggableOn::Tag.named_like_any(
|
|
28
|
+
it 'should find both tags' do
|
|
29
|
+
expect(ActsAsTaggableOn::Tag.named_like_any(%w(awesome epic)).count).to eq(2)
|
|
27
30
|
end
|
|
28
31
|
end
|
|
29
32
|
end
|
|
30
33
|
|
|
31
|
-
context
|
|
32
|
-
if
|
|
34
|
+
context 'case insensitive collation without indexes or case sensitive collation with indexes' do
|
|
35
|
+
if ActsAsTaggableOn::Utils.using_case_insensitive_collation?
|
|
33
36
|
include_context 'without unique index'
|
|
34
37
|
end
|
|
35
38
|
|
|
36
39
|
before(:each) do
|
|
37
|
-
ActsAsTaggableOn::Tag.create(:
|
|
38
|
-
ActsAsTaggableOn::Tag.create(:
|
|
39
|
-
ActsAsTaggableOn::Tag.create(:
|
|
40
|
+
ActsAsTaggableOn::Tag.create(name: 'Awesome')
|
|
41
|
+
ActsAsTaggableOn::Tag.create(name: 'awesome')
|
|
42
|
+
ActsAsTaggableOn::Tag.create(name: 'epic')
|
|
40
43
|
end
|
|
41
44
|
|
|
42
|
-
it
|
|
43
|
-
ActsAsTaggableOn::Tag.named_like_any(
|
|
45
|
+
it 'should find both tags' do
|
|
46
|
+
expect(ActsAsTaggableOn::Tag.named_like_any(%w(awesome epic)).count).to eq(3)
|
|
44
47
|
end
|
|
45
48
|
end
|
|
46
49
|
end
|
|
47
50
|
|
|
48
|
-
describe
|
|
51
|
+
describe 'find or create by name' do
|
|
49
52
|
before(:each) do
|
|
50
|
-
@tag.name =
|
|
53
|
+
@tag.name = 'awesome'
|
|
51
54
|
@tag.save
|
|
52
55
|
end
|
|
53
56
|
|
|
54
|
-
it
|
|
55
|
-
ActsAsTaggableOn::Tag.find_or_create_with_like_by_name(
|
|
57
|
+
it 'should find by name' do
|
|
58
|
+
expect(ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('awesome')).to eq(@tag)
|
|
56
59
|
end
|
|
57
60
|
|
|
58
|
-
it
|
|
59
|
-
ActsAsTaggableOn::Tag.find_or_create_with_like_by_name(
|
|
61
|
+
it 'should find by name case insensitive' do
|
|
62
|
+
expect(ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('AWESOME')).to eq(@tag)
|
|
60
63
|
end
|
|
61
64
|
|
|
62
|
-
it
|
|
63
|
-
|
|
64
|
-
ActsAsTaggableOn::Tag.find_or_create_with_like_by_name(
|
|
65
|
-
}.
|
|
65
|
+
it 'should create by name' do
|
|
66
|
+
expect(-> {
|
|
67
|
+
ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('epic')
|
|
68
|
+
}).to change(ActsAsTaggableOn::Tag, :count).by(1)
|
|
66
69
|
end
|
|
67
70
|
end
|
|
68
71
|
|
|
69
|
-
unless ActsAsTaggableOn::
|
|
70
|
-
describe
|
|
72
|
+
unless ActsAsTaggableOn::Utils.using_sqlite?
|
|
73
|
+
describe 'find or create by unicode name' do
|
|
71
74
|
before(:each) do
|
|
72
|
-
@tag.name =
|
|
75
|
+
@tag.name = 'привет'
|
|
73
76
|
@tag.save
|
|
74
77
|
end
|
|
75
78
|
|
|
76
|
-
it
|
|
77
|
-
ActsAsTaggableOn::Tag.find_or_create_with_like_by_name(
|
|
79
|
+
it 'should find by name' do
|
|
80
|
+
expect(ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('привет')).to eq(@tag)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it 'should find by name case insensitive' do
|
|
84
|
+
expect(ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('ПРИВЕТ')).to eq(@tag)
|
|
78
85
|
end
|
|
79
86
|
|
|
80
|
-
|
|
81
|
-
|
|
87
|
+
if ActsAsTaggableOn::Utils.using_case_insensitive_collation?
|
|
88
|
+
it 'should find by name accent insensitive' do
|
|
89
|
+
@tag.name = 'inupiat'
|
|
90
|
+
@tag.save
|
|
91
|
+
expect(ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('Iñupiat')).to eq(@tag)
|
|
92
|
+
end
|
|
82
93
|
end
|
|
83
94
|
end
|
|
84
95
|
end
|
|
85
96
|
|
|
86
|
-
describe
|
|
97
|
+
describe 'find or create all by any name' do
|
|
87
98
|
before(:each) do
|
|
88
|
-
@tag.name =
|
|
99
|
+
@tag.name = 'awesome'
|
|
89
100
|
@tag.save
|
|
90
101
|
end
|
|
91
102
|
|
|
92
|
-
it
|
|
93
|
-
ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name(
|
|
103
|
+
it 'should find by name' do
|
|
104
|
+
expect(ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name('awesome')).to eq([@tag])
|
|
94
105
|
end
|
|
95
106
|
|
|
96
|
-
it
|
|
97
|
-
ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name(
|
|
107
|
+
it 'should find by name case insensitive' do
|
|
108
|
+
expect(ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name('AWESOME')).to eq([@tag])
|
|
98
109
|
end
|
|
99
110
|
|
|
100
|
-
context
|
|
101
|
-
if
|
|
111
|
+
context 'case sensitive' do
|
|
112
|
+
if ActsAsTaggableOn::Utils.using_case_insensitive_collation?
|
|
102
113
|
include_context 'without unique index'
|
|
103
114
|
end
|
|
104
115
|
|
|
105
|
-
it
|
|
116
|
+
it 'should find by name case sensitive' do
|
|
106
117
|
ActsAsTaggableOn.strict_case_match = true
|
|
107
118
|
expect {
|
|
108
|
-
ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name(
|
|
119
|
+
ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name('AWESOME')
|
|
109
120
|
}.to change(ActsAsTaggableOn::Tag, :count).by(1)
|
|
110
121
|
end
|
|
111
122
|
end
|
|
112
123
|
|
|
113
|
-
it
|
|
124
|
+
it 'should create by name' do
|
|
114
125
|
expect {
|
|
115
|
-
ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name(
|
|
126
|
+
ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name('epic')
|
|
116
127
|
}.to change(ActsAsTaggableOn::Tag, :count).by(1)
|
|
117
128
|
end
|
|
118
129
|
|
|
119
|
-
context
|
|
120
|
-
if
|
|
130
|
+
context 'case sensitive' do
|
|
131
|
+
if ActsAsTaggableOn::Utils.using_case_insensitive_collation?
|
|
121
132
|
include_context 'without unique index'
|
|
122
133
|
end
|
|
123
134
|
|
|
124
|
-
it
|
|
135
|
+
it 'should find or create by name case sensitive' do
|
|
125
136
|
ActsAsTaggableOn.strict_case_match = true
|
|
126
137
|
expect {
|
|
127
|
-
ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name(
|
|
138
|
+
expect(ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name('AWESOME', 'awesome').map(&:name)).to eq(%w(AWESOME awesome))
|
|
128
139
|
}.to change(ActsAsTaggableOn::Tag, :count).by(1)
|
|
129
140
|
end
|
|
130
141
|
end
|
|
131
142
|
|
|
132
|
-
it
|
|
143
|
+
it 'should find or create by name' do
|
|
133
144
|
expect {
|
|
134
|
-
ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name(
|
|
145
|
+
expect(ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name('awesome', 'epic').map(&:name)).to eq(%w(awesome epic))
|
|
135
146
|
}.to change(ActsAsTaggableOn::Tag, :count).by(1)
|
|
136
147
|
end
|
|
137
148
|
|
|
138
|
-
it
|
|
139
|
-
ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name([]).
|
|
149
|
+
it 'should return an empty array if no tags are specified' do
|
|
150
|
+
expect(ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name([])).to be_empty
|
|
140
151
|
end
|
|
141
152
|
end
|
|
142
153
|
|
|
143
|
-
it
|
|
154
|
+
it 'should require a name' do
|
|
144
155
|
@tag.valid?
|
|
156
|
+
#TODO, we should find another way to check this
|
|
157
|
+
expect(@tag.errors[:name]).to eq(["can't be blank"])
|
|
145
158
|
|
|
146
|
-
@tag.
|
|
147
|
-
|
|
148
|
-
@tag.name = "something"
|
|
159
|
+
@tag.name = 'something'
|
|
149
160
|
@tag.valid?
|
|
150
161
|
|
|
151
|
-
@tag.errors[:name].
|
|
162
|
+
expect(@tag.errors[:name]).to be_empty
|
|
152
163
|
end
|
|
153
164
|
|
|
154
|
-
it
|
|
155
|
-
@tag.name =
|
|
165
|
+
it 'should limit the name length to 255 or less characters' do
|
|
166
|
+
@tag.name = 'fgkgnkkgjymkypbuozmwwghblmzpqfsgjasflblywhgkwndnkzeifalfcpeaeqychjuuowlacmuidnnrkprgpcpybarbkrmziqihcrxirlokhnzfvmtzixgvhlxzncyywficpraxfnjptxxhkqmvicbcdcynkjvziefqzyndxkjmsjlvyvbwraklbalykyxoliqdlreeykuphdtmzfdwpphmrqvwvqffojkqhlzvinqajsxbszyvrqqyzusxranr'
|
|
156
167
|
@tag.valid?
|
|
157
|
-
|
|
168
|
+
#TODO, we should find another way to check this
|
|
169
|
+
expect(@tag.errors[:name]).to eq(['is too long (maximum is 255 characters)'])
|
|
158
170
|
|
|
159
|
-
@tag.name =
|
|
171
|
+
@tag.name = 'fgkgnkkgjymkypbuozmwwghblmzpqfsgjasflblywhgkwndnkzeifalfcpeaeqychjuuowlacmuidnnrkprgpcpybarbkrmziqihcrxirlokhnzfvmtzixgvhlxzncyywficpraxfnjptxxhkqmvicbcdcynkjvziefqzyndxkjmsjlvyvbwraklbalykyxoliqdlreeykuphdtmzfdwpphmrqvwvqffojkqhlzvinqajsxbszyvrqqyzusxran'
|
|
160
172
|
@tag.valid?
|
|
161
|
-
@tag.errors[:name].
|
|
173
|
+
expect(@tag.errors[:name]).to be_empty
|
|
162
174
|
end
|
|
163
175
|
|
|
164
|
-
it
|
|
165
|
-
@tag.name =
|
|
166
|
-
new_tag = ActsAsTaggableOn::Tag.new(:
|
|
167
|
-
new_tag.
|
|
176
|
+
it 'should equal a tag with the same name' do
|
|
177
|
+
@tag.name = 'awesome'
|
|
178
|
+
new_tag = ActsAsTaggableOn::Tag.new(name: 'awesome')
|
|
179
|
+
expect(new_tag).to eq(@tag)
|
|
168
180
|
end
|
|
169
181
|
|
|
170
|
-
it
|
|
171
|
-
@tag.name =
|
|
172
|
-
@tag.to_s.
|
|
182
|
+
it 'should return its name when to_s is called' do
|
|
183
|
+
@tag.name = 'cool'
|
|
184
|
+
expect(@tag.to_s).to eq('cool')
|
|
173
185
|
end
|
|
174
186
|
|
|
175
|
-
it
|
|
176
|
-
@tag.name =
|
|
187
|
+
it 'have named_scope named(something)' do
|
|
188
|
+
@tag.name = 'cool'
|
|
177
189
|
@tag.save!
|
|
178
|
-
ActsAsTaggableOn::Tag.named('cool').
|
|
190
|
+
expect(ActsAsTaggableOn::Tag.named('cool')).to include(@tag)
|
|
179
191
|
end
|
|
180
192
|
|
|
181
|
-
it
|
|
182
|
-
@tag.name =
|
|
193
|
+
it 'have named_scope named_like(something)' do
|
|
194
|
+
@tag.name = 'cool'
|
|
183
195
|
@tag.save!
|
|
184
|
-
@another_tag = ActsAsTaggableOn::Tag.create!(:
|
|
185
|
-
ActsAsTaggableOn::Tag.named_like('cool').
|
|
196
|
+
@another_tag = ActsAsTaggableOn::Tag.create!(name: 'coolip')
|
|
197
|
+
expect(ActsAsTaggableOn::Tag.named_like('cool')).to include(@tag, @another_tag)
|
|
186
198
|
end
|
|
187
199
|
|
|
188
|
-
describe
|
|
200
|
+
describe 'escape wildcard symbols in like requests' do
|
|
189
201
|
before(:each) do
|
|
190
|
-
@tag.name =
|
|
202
|
+
@tag.name = 'cool'
|
|
191
203
|
@tag.save
|
|
192
|
-
@another_tag = ActsAsTaggableOn::Tag.create!(:
|
|
193
|
-
@another_tag2 = ActsAsTaggableOn::Tag.create!(:
|
|
204
|
+
@another_tag = ActsAsTaggableOn::Tag.create!(name: 'coo%')
|
|
205
|
+
@another_tag2 = ActsAsTaggableOn::Tag.create!(name: 'coolish')
|
|
194
206
|
end
|
|
195
207
|
|
|
196
208
|
it "return escaped result when '%' char present in tag" do
|
|
197
|
-
|
|
198
|
-
|
|
209
|
+
expect(ActsAsTaggableOn::Tag.named_like('coo%')).to_not include(@tag)
|
|
210
|
+
expect(ActsAsTaggableOn::Tag.named_like('coo%')).to include(@another_tag)
|
|
199
211
|
end
|
|
200
212
|
|
|
201
213
|
end
|
|
202
214
|
|
|
203
|
-
describe
|
|
215
|
+
describe 'when using strict_case_match' do
|
|
204
216
|
before do
|
|
205
217
|
ActsAsTaggableOn.strict_case_match = true
|
|
206
|
-
@tag.name =
|
|
218
|
+
@tag.name = 'awesome'
|
|
207
219
|
@tag.save!
|
|
208
220
|
end
|
|
209
221
|
|
|
@@ -211,71 +223,72 @@ describe ActsAsTaggableOn::Tag do
|
|
|
211
223
|
ActsAsTaggableOn.strict_case_match = false
|
|
212
224
|
end
|
|
213
225
|
|
|
214
|
-
it
|
|
215
|
-
ActsAsTaggableOn::Tag.find_or_create_with_like_by_name(
|
|
226
|
+
it 'should find by name' do
|
|
227
|
+
expect(ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('awesome')).to eq(@tag)
|
|
216
228
|
end
|
|
217
229
|
|
|
218
|
-
context
|
|
219
|
-
if
|
|
230
|
+
context 'case sensitive' do
|
|
231
|
+
if ActsAsTaggableOn::Utils.using_case_insensitive_collation?
|
|
220
232
|
include_context 'without unique index'
|
|
221
233
|
end
|
|
222
234
|
|
|
223
|
-
it
|
|
235
|
+
it 'should find by name case sensitively' do
|
|
224
236
|
expect {
|
|
225
|
-
ActsAsTaggableOn::Tag.find_or_create_with_like_by_name(
|
|
237
|
+
ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('AWESOME')
|
|
226
238
|
}.to change(ActsAsTaggableOn::Tag, :count)
|
|
227
239
|
|
|
228
|
-
ActsAsTaggableOn::Tag.last.name.
|
|
240
|
+
expect(ActsAsTaggableOn::Tag.last.name).to eq('AWESOME')
|
|
229
241
|
end
|
|
230
242
|
end
|
|
231
243
|
|
|
232
|
-
context
|
|
233
|
-
if
|
|
244
|
+
context 'case sensitive' do
|
|
245
|
+
if ActsAsTaggableOn::Utils.using_case_insensitive_collation?
|
|
234
246
|
include_context 'without unique index'
|
|
235
247
|
end
|
|
236
248
|
|
|
237
|
-
it
|
|
238
|
-
uppercase_tag = ActsAsTaggableOn::Tag.create(:
|
|
239
|
-
@tag.name
|
|
249
|
+
it 'should have a named_scope named(something) that matches exactly' do
|
|
250
|
+
uppercase_tag = ActsAsTaggableOn::Tag.create(name: 'Cool')
|
|
251
|
+
@tag.name = 'cool'
|
|
240
252
|
@tag.save!
|
|
241
253
|
|
|
242
|
-
ActsAsTaggableOn::Tag.named('cool').
|
|
243
|
-
ActsAsTaggableOn::Tag.named('cool').
|
|
254
|
+
expect(ActsAsTaggableOn::Tag.named('cool')).to include(@tag)
|
|
255
|
+
expect(ActsAsTaggableOn::Tag.named('cool')).to_not include(uppercase_tag)
|
|
244
256
|
end
|
|
245
257
|
end
|
|
246
258
|
|
|
247
|
-
it
|
|
259
|
+
it 'should not change enconding' do
|
|
248
260
|
name = "\u3042"
|
|
249
261
|
original_encoding = name.encoding
|
|
250
|
-
ActsAsTaggableOn::Tag.find_or_create_with_like_by_name(name)
|
|
251
|
-
|
|
262
|
+
record = ActsAsTaggableOn::Tag.find_or_create_with_like_by_name(name)
|
|
263
|
+
record.reload
|
|
264
|
+
expect(record.name.encoding).to eq(original_encoding)
|
|
252
265
|
end
|
|
253
266
|
end
|
|
254
267
|
|
|
255
|
-
describe
|
|
256
|
-
let(:duplicate_tag) { ActsAsTaggableOn::Tag.new(:
|
|
268
|
+
describe 'name uniqeness validation' do
|
|
269
|
+
let(:duplicate_tag) { ActsAsTaggableOn::Tag.new(name: 'ror') }
|
|
257
270
|
|
|
258
|
-
before { ActsAsTaggableOn::Tag.create(:
|
|
271
|
+
before { ActsAsTaggableOn::Tag.create(name: 'ror') }
|
|
259
272
|
|
|
260
273
|
context "when don't need unique names" do
|
|
261
274
|
include_context 'without unique index'
|
|
262
|
-
it
|
|
263
|
-
duplicate_tag.
|
|
275
|
+
it 'should not run uniqueness validation' do
|
|
276
|
+
allow(duplicate_tag).to receive(:validates_name_uniqueness?) { false }
|
|
264
277
|
duplicate_tag.save
|
|
265
|
-
duplicate_tag.
|
|
278
|
+
expect(duplicate_tag).to be_persisted
|
|
266
279
|
end
|
|
267
280
|
end
|
|
268
281
|
|
|
269
|
-
context
|
|
270
|
-
it
|
|
271
|
-
duplicate_tag.
|
|
282
|
+
context 'when do need unique names' do
|
|
283
|
+
it 'should run uniqueness validation' do
|
|
284
|
+
expect(duplicate_tag).to_not be_valid
|
|
272
285
|
end
|
|
273
286
|
|
|
274
|
-
it
|
|
287
|
+
it 'add error to name' do
|
|
275
288
|
duplicate_tag.save
|
|
276
289
|
|
|
277
|
-
duplicate_tag.
|
|
278
|
-
duplicate_tag.errors.messages[:name].
|
|
290
|
+
expect(duplicate_tag.errors.size).to eq(1)
|
|
291
|
+
expect(duplicate_tag.errors.messages[:name]).to include('has already been taken')
|
|
279
292
|
end
|
|
280
293
|
end
|
|
281
294
|
end
|