acts-as-taggable-on 12.0.0 → 13.0.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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/lib/acts-as-taggable-on/tag.rb +5 -13
  3. data/lib/acts-as-taggable-on/tag_list.rb +1 -1
  4. data/lib/acts-as-taggable-on/taggable/core.rb +0 -3
  5. data/lib/acts-as-taggable-on/taggable/tagged_with_query.rb +0 -5
  6. data/lib/acts-as-taggable-on/version.rb +1 -1
  7. data/lib/acts-as-taggable-on.rb +1 -1
  8. metadata +10 -170
  9. data/.github/workflows/spec.yml +0 -73
  10. data/.gitignore +0 -13
  11. data/.rspec +0 -2
  12. data/Appraisals +0 -23
  13. data/CHANGELOG.md +0 -379
  14. data/CONTRIBUTING.md +0 -57
  15. data/Gemfile +0 -11
  16. data/Guardfile +0 -5
  17. data/README.md +0 -596
  18. data/Rakefile +0 -21
  19. data/acts-as-taggable-on.gemspec +0 -32
  20. data/docker-compose.yml +0 -15
  21. data/gemfiles/activerecord_7.1.gemfile +0 -18
  22. data/gemfiles/activerecord_7.2.gemfile +0 -18
  23. data/gemfiles/activerecord_8.0.gemfile +0 -19
  24. data/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb +0 -272
  25. data/spec/acts_as_taggable_on/acts_as_tagger_spec.rb +0 -112
  26. data/spec/acts_as_taggable_on/caching_spec.rb +0 -125
  27. data/spec/acts_as_taggable_on/default_parser_spec.rb +0 -47
  28. data/spec/acts_as_taggable_on/dirty_spec.rb +0 -142
  29. data/spec/acts_as_taggable_on/generic_parser_spec.rb +0 -14
  30. data/spec/acts_as_taggable_on/related_spec.rb +0 -99
  31. data/spec/acts_as_taggable_on/single_table_inheritance_spec.rb +0 -231
  32. data/spec/acts_as_taggable_on/tag_list_spec.rb +0 -176
  33. data/spec/acts_as_taggable_on/tag_spec.rb +0 -398
  34. data/spec/acts_as_taggable_on/taggable_spec.rb +0 -828
  35. data/spec/acts_as_taggable_on/tagger_spec.rb +0 -153
  36. data/spec/acts_as_taggable_on/tagging_spec.rb +0 -169
  37. data/spec/acts_as_taggable_on/tags_helper_spec.rb +0 -45
  38. data/spec/acts_as_taggable_on/utils_spec.rb +0 -23
  39. data/spec/internal/app/models/altered_inheriting_taggable_model.rb +0 -5
  40. data/spec/internal/app/models/cached_model.rb +0 -3
  41. data/spec/internal/app/models/cached_model_with_array.rb +0 -11
  42. data/spec/internal/app/models/columns_override_model.rb +0 -5
  43. data/spec/internal/app/models/company.rb +0 -15
  44. data/spec/internal/app/models/inheriting_taggable_model.rb +0 -4
  45. data/spec/internal/app/models/market.rb +0 -2
  46. data/spec/internal/app/models/non_standard_id_taggable_model.rb +0 -8
  47. data/spec/internal/app/models/ordered_taggable_model.rb +0 -4
  48. data/spec/internal/app/models/other_cached_model.rb +0 -3
  49. data/spec/internal/app/models/other_taggable_model.rb +0 -4
  50. data/spec/internal/app/models/student.rb +0 -4
  51. data/spec/internal/app/models/taggable_model.rb +0 -16
  52. data/spec/internal/app/models/untaggable_model.rb +0 -3
  53. data/spec/internal/app/models/user.rb +0 -3
  54. data/spec/internal/config/database.yml.sample +0 -15
  55. data/spec/internal/db/schema.rb +0 -113
  56. data/spec/spec_helper.rb +0 -20
  57. data/spec/support/0-helpers.rb +0 -32
  58. data/spec/support/array.rb +0 -9
  59. data/spec/support/database.rb +0 -38
  60. data/spec/support/database_cleaner.rb +0 -25
@@ -1,398 +0,0 @@
1
- # -*- encoding : utf-8 -*-
2
- require 'spec_helper'
3
- require 'db/migrate/2_add_missing_unique_indices.rb'
4
-
5
-
6
- shared_examples_for 'without unique index' do
7
- prepend_before(:all) { AddMissingUniqueIndices.down }
8
- append_after(:all) do
9
- ActsAsTaggableOn::Tag.delete_all
10
- AddMissingUniqueIndices.up
11
- end
12
- end
13
-
14
- describe ActsAsTaggableOn::Tag do
15
- before(:each) do
16
- @tag = ActsAsTaggableOn::Tag.new
17
- @user = TaggableModel.create(name: 'Pablo', tenant_id: 100)
18
- end
19
-
20
-
21
- describe 'named like any' do
22
- context 'case insensitive collation and unique index on tag name', if: using_case_insensitive_collation? do
23
- before(:each) do
24
- ActsAsTaggableOn::Tag.create(name: 'Awesome')
25
- ActsAsTaggableOn::Tag.create(name: 'epic')
26
- end
27
-
28
- it 'should find both tags' do
29
- expect(ActsAsTaggableOn::Tag.named_like_any(%w(awesome epic)).count).to eq(2)
30
- end
31
- end
32
-
33
- context 'case insensitive collation without indexes or case sensitive collation with indexes' do
34
- if using_case_insensitive_collation?
35
- include_context 'without unique index'
36
- end
37
-
38
- before(:each) do
39
- ActsAsTaggableOn::Tag.create(name: 'Awesome')
40
- ActsAsTaggableOn::Tag.create(name: 'awesome')
41
- ActsAsTaggableOn::Tag.create(name: 'epic')
42
- end
43
-
44
- it 'should find both tags' do
45
- expect(ActsAsTaggableOn::Tag.named_like_any(%w(awesome epic)).count).to eq(3)
46
- end
47
- end
48
- end
49
-
50
- describe 'named any' do
51
- context 'with some special characters combinations', if: using_mysql? do
52
- it 'should not raise an invalid encoding exception' do
53
- expect{ActsAsTaggableOn::Tag.named_any(["holä", "hol'ä"])}.not_to raise_error
54
- end
55
- end
56
- end
57
-
58
- describe 'for context' do
59
- before(:each) do
60
- @user.skill_list.add('ruby')
61
- @user.save
62
- end
63
-
64
- it 'should return tags that have been used in the given context' do
65
- expect(ActsAsTaggableOn::Tag.for_context('skills').pluck(:name)).to include('ruby')
66
- end
67
-
68
- it 'should not return tags that have been used in other contexts' do
69
- expect(ActsAsTaggableOn::Tag.for_context('needs').pluck(:name)).to_not include('ruby')
70
- end
71
- end
72
-
73
- describe 'for tenant' do
74
- before(:each) do
75
- @user.skill_list.add('ruby')
76
- @user.save
77
- end
78
-
79
- it 'should return tags for the tenant' do
80
- expect(ActsAsTaggableOn::Tag.for_tenant('100').pluck(:name)).to include('ruby')
81
- end
82
-
83
- it 'should not return tags for other tenants' do
84
- expect(ActsAsTaggableOn::Tag.for_tenant('200').pluck(:name)).to_not include('ruby')
85
- end
86
- end
87
-
88
- describe 'find or create by name' do
89
- before(:each) do
90
- @tag.name = 'awesome'
91
- @tag.save
92
- end
93
-
94
- it 'should find by name' do
95
- expect(ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('awesome')).to eq(@tag)
96
- end
97
-
98
- it 'should find by name case insensitive' do
99
- expect(ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('AWESOME')).to eq(@tag)
100
- end
101
-
102
- it 'should create by name' do
103
- expect {
104
- ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('epic')
105
- }.to change(ActsAsTaggableOn::Tag, :count).by(1)
106
- end
107
- end
108
-
109
- describe 'find or create by unicode name', unless: using_sqlite? do
110
- before(:each) do
111
- @tag.name = 'привет'
112
- @tag.save
113
- end
114
-
115
- it 'should find by name' do
116
- expect(ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('привет')).to eq(@tag)
117
- end
118
-
119
- it 'should find by name case insensitive' do
120
- expect(ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('ПРИВЕТ')).to eq(@tag)
121
- end
122
-
123
- it 'should find by name accent insensitive', if: using_case_insensitive_collation? do
124
- @tag.name = 'inupiat'
125
- @tag.save
126
- expect(ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('Iñupiat')).to eq(@tag)
127
- end
128
- end
129
-
130
- describe 'find or create all by any name' do
131
- before(:each) do
132
- @tag.name = 'awesome'
133
- @tag.save
134
- end
135
-
136
- it 'should find by name' do
137
- expect(ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name('awesome')).to eq([@tag])
138
- end
139
-
140
- it 'should find by name case insensitive' do
141
- expect(ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name('AWESOME')).to eq([@tag])
142
- end
143
-
144
- context 'case sensitive' do
145
- if using_case_insensitive_collation?
146
- include_context 'without unique index'
147
- end
148
-
149
- it 'should find by name case sensitive' do
150
- ActsAsTaggableOn.strict_case_match = true
151
- expect {
152
- ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name('AWESOME')
153
- }.to change(ActsAsTaggableOn::Tag, :count).by(1)
154
- end
155
- end
156
-
157
- it 'should create by name' do
158
- expect {
159
- ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name('epic')
160
- }.to change(ActsAsTaggableOn::Tag, :count).by(1)
161
- end
162
-
163
- context 'case sensitive' do
164
- if using_case_insensitive_collation?
165
- include_context 'without unique index'
166
- end
167
-
168
- it 'should find or create by name case sensitive' do
169
- ActsAsTaggableOn.strict_case_match = true
170
- expect {
171
- expect(ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name('AWESOME', 'awesome').map(&:name)).to eq(%w(AWESOME awesome))
172
- }.to change(ActsAsTaggableOn::Tag, :count).by(1)
173
- end
174
- end
175
-
176
- it 'should find or create by name' do
177
- expect {
178
- expect(ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name('awesome', 'epic').map(&:name)).to eq(%w(awesome epic))
179
- }.to change(ActsAsTaggableOn::Tag, :count).by(1)
180
- end
181
-
182
- it 'should return an empty array if no tags are specified' do
183
- expect(ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name([])).to be_empty
184
- end
185
-
186
- context 'another tag is created concurrently', :database_cleaner_delete, if: supports_concurrency? do
187
- it 'retries and finds tag if tag with same name created concurrently' do
188
- tag_name = 'super'
189
-
190
- expect(ActsAsTaggableOn::Tag).to receive(:create).with(name: tag_name) do
191
- # Simulate concurrent tag creation
192
- Thread.new do
193
- ActsAsTaggableOn::Tag.new(name: tag_name).save!
194
- end.join
195
-
196
- raise ActiveRecord::RecordNotUnique
197
- end
198
-
199
- expect {
200
- ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name(tag_name)
201
- }.to change(ActsAsTaggableOn::Tag, :count).by(1)
202
- end
203
- end
204
- end
205
-
206
- it 'should require a name' do
207
- @tag.valid?
208
- #TODO, we should find another way to check this
209
- expect(@tag.errors[:name]).to eq(["can't be blank"])
210
-
211
- @tag.name = 'something'
212
- @tag.valid?
213
-
214
- expect(@tag.errors[:name]).to be_empty
215
- end
216
-
217
- it 'should limit the name length to 255 or less characters' do
218
- @tag.name = 'fgkgnkkgjymkypbuozmwwghblmzpqfsgjasflblywhgkwndnkzeifalfcpeaeqychjuuowlacmuidnnrkprgpcpybarbkrmziqihcrxirlokhnzfvmtzixgvhlxzncyywficpraxfnjptxxhkqmvicbcdcynkjvziefqzyndxkjmsjlvyvbwraklbalykyxoliqdlreeykuphdtmzfdwpphmrqvwvqffojkqhlzvinqajsxbszyvrqqyzusxranr'
219
- @tag.valid?
220
- #TODO, we should find another way to check this
221
- expect(@tag.errors[:name]).to eq(['is too long (maximum is 255 characters)'])
222
-
223
- @tag.name = 'fgkgnkkgjymkypbuozmwwghblmzpqfsgjasflblywhgkwndnkzeifalfcpeaeqychjuuowlacmuidnnrkprgpcpybarbkrmziqihcrxirlokhnzfvmtzixgvhlxzncyywficpraxfnjptxxhkqmvicbcdcynkjvziefqzyndxkjmsjlvyvbwraklbalykyxoliqdlreeykuphdtmzfdwpphmrqvwvqffojkqhlzvinqajsxbszyvrqqyzusxran'
224
- @tag.valid?
225
- expect(@tag.errors[:name]).to be_empty
226
- end
227
-
228
- it 'should equal a tag with the same name' do
229
- @tag.name = 'awesome'
230
- new_tag = ActsAsTaggableOn::Tag.new(name: 'awesome')
231
- expect(new_tag).to eq(@tag)
232
- end
233
-
234
- it 'should return its name when to_s is called' do
235
- @tag.name = 'cool'
236
- expect(@tag.to_s).to eq('cool')
237
- end
238
-
239
- it 'have named_scope named(something)' do
240
- @tag.name = 'cool'
241
- @tag.save!
242
- expect(ActsAsTaggableOn::Tag.named('cool')).to include(@tag)
243
- end
244
-
245
- it 'have named_scope named_like(something)' do
246
- @tag.name = 'cool'
247
- @tag.save!
248
- @another_tag = ActsAsTaggableOn::Tag.create!(name: 'coolip')
249
- expect(ActsAsTaggableOn::Tag.named_like('cool')).to include(@tag, @another_tag)
250
- end
251
-
252
- describe 'escape wildcard symbols in like requests' do
253
- before(:each) do
254
- @tag.name = 'cool'
255
- @tag.save
256
- @another_tag = ActsAsTaggableOn::Tag.create!(name: 'coo%')
257
- @another_tag2 = ActsAsTaggableOn::Tag.create!(name: 'coolish')
258
- end
259
-
260
- it "return escaped result when '%' char present in tag" do
261
- expect(ActsAsTaggableOn::Tag.named_like('coo%')).to_not include(@tag)
262
- expect(ActsAsTaggableOn::Tag.named_like('coo%')).to include(@another_tag)
263
- end
264
-
265
- end
266
-
267
- describe 'when using strict_case_match' do
268
- before do
269
- ActsAsTaggableOn.strict_case_match = true
270
- @tag.name = 'awesome'
271
- @tag.save!
272
- end
273
-
274
- after do
275
- ActsAsTaggableOn.strict_case_match = false
276
- end
277
-
278
- it 'should find by name' do
279
- expect(ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('awesome')).to eq(@tag)
280
- end
281
-
282
- context 'case sensitive' do
283
- if using_case_insensitive_collation?
284
- include_context 'without unique index'
285
- end
286
-
287
- it 'should find by name case sensitively' do
288
- expect {
289
- ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('AWESOME')
290
- }.to change(ActsAsTaggableOn::Tag, :count)
291
-
292
- expect(ActsAsTaggableOn::Tag.last.name).to eq('AWESOME')
293
- end
294
- end
295
-
296
- context 'case sensitive' do
297
- if using_case_insensitive_collation?
298
- include_context 'without unique index'
299
- end
300
-
301
- it 'should have a named_scope named(something) that matches exactly' do
302
- uppercase_tag = ActsAsTaggableOn::Tag.create(name: 'Cool')
303
- @tag.name = 'cool'
304
- @tag.save!
305
-
306
- expect(ActsAsTaggableOn::Tag.named('cool')).to include(@tag)
307
- expect(ActsAsTaggableOn::Tag.named('cool')).to_not include(uppercase_tag)
308
- end
309
- end
310
-
311
- it 'should not change encoding' do
312
- name = "\u3042"
313
- original_encoding = name.encoding
314
- record = ActsAsTaggableOn::Tag.find_or_create_with_like_by_name(name)
315
- record.reload
316
- expect(record.name.encoding).to eq(original_encoding)
317
- end
318
-
319
- context 'named any with some special characters combinations', if: using_mysql? do
320
- it 'should not raise an invalid encoding exception' do
321
- expect{ActsAsTaggableOn::Tag.named_any(["holä", "hol'ä"])}.not_to raise_error
322
- end
323
- end
324
- end
325
-
326
- describe 'name uniqeness validation' do
327
- let(:duplicate_tag) { ActsAsTaggableOn::Tag.new(name: 'ror') }
328
-
329
- before { ActsAsTaggableOn::Tag.create(name: 'ror') }
330
-
331
- context "when don't need unique names" do
332
- include_context 'without unique index'
333
- it 'should not run uniqueness validation' do
334
- allow(duplicate_tag).to receive(:validates_name_uniqueness?) { false }
335
- duplicate_tag.save
336
- expect(duplicate_tag).to be_persisted
337
- end
338
- end
339
-
340
- context 'when do need unique names' do
341
- it 'should run uniqueness validation' do
342
- expect(duplicate_tag).to_not be_valid
343
- end
344
-
345
- it 'add error to name' do
346
- duplicate_tag.save
347
-
348
- expect(duplicate_tag.errors.size).to eq(1)
349
- expect(duplicate_tag.errors.messages[:name]).to include('has already been taken')
350
- end
351
- end
352
- end
353
-
354
- describe 'popular tags' do
355
- before do
356
- %w(sports rails linux tennis golden_syrup).each_with_index do |t, i|
357
- tag = ActsAsTaggableOn::Tag.new(name: t)
358
- tag.taggings_count = i
359
- tag.save!
360
- end
361
- end
362
-
363
- it 'should find the most popular tags' do
364
- expect(ActsAsTaggableOn::Tag.most_used(3).first.name).to eq("golden_syrup")
365
- expect(ActsAsTaggableOn::Tag.most_used(3).length).to eq(3)
366
- end
367
-
368
- it 'should find the least popular tags' do
369
- expect(ActsAsTaggableOn::Tag.least_used(3).first.name).to eq("sports")
370
- expect(ActsAsTaggableOn::Tag.least_used(3).length).to eq(3)
371
- end
372
- end
373
-
374
- describe 'base_class' do
375
- before do
376
- class Foo < ActiveRecord::Base; end
377
- end
378
-
379
- context "default" do
380
- it "inherits from ActiveRecord::Base" do
381
-
382
- expect(ActsAsTaggableOn::Tag.ancestors).to include(ActiveRecord::Base)
383
- expect(ActsAsTaggableOn::Tag.ancestors).to_not include(Foo)
384
- end
385
- end
386
-
387
- context "custom" do
388
- it "inherits from custom class" do
389
-
390
- ActsAsTaggableOn.base_class = 'Foo'
391
- hide_const("ActsAsTaggableOn::Tag")
392
- load("lib/acts-as-taggable-on/tag.rb")
393
-
394
- expect(ActsAsTaggableOn::Tag.ancestors).to include(Foo)
395
- end
396
- end
397
- end
398
- end