acts-as-taggable-on 2.0.6 → 2.3.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 (49) hide show
  1. data/.gitignore +10 -0
  2. data/.rspec +2 -0
  3. data/.travis.yml +9 -0
  4. data/CHANGELOG +10 -0
  5. data/Gemfile +2 -9
  6. data/Guardfile +5 -0
  7. data/README.rdoc +89 -66
  8. data/Rakefile +9 -55
  9. data/acts-as-taggable-on.gemspec +28 -0
  10. data/lib/acts-as-taggable-on/version.rb +4 -0
  11. data/lib/acts-as-taggable-on.rb +33 -4
  12. data/lib/acts_as_taggable_on/acts_as_taggable_on/cache.rb +4 -4
  13. data/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb +38 -43
  14. data/lib/acts_as_taggable_on/acts_as_taggable_on/core.rb +146 -38
  15. data/lib/acts_as_taggable_on/acts_as_taggable_on/dirty.rb +37 -0
  16. data/lib/acts_as_taggable_on/acts_as_taggable_on/ownership.rb +36 -11
  17. data/lib/acts_as_taggable_on/acts_as_taggable_on/related.rb +23 -15
  18. data/lib/acts_as_taggable_on/tag.rb +16 -13
  19. data/lib/acts_as_taggable_on/tag_list.rb +13 -12
  20. data/lib/acts_as_taggable_on/taggable.rb +102 -0
  21. data/lib/acts_as_taggable_on/{acts_as_tagger.rb → tagger.rb} +3 -3
  22. data/lib/acts_as_taggable_on/tagging.rb +12 -2
  23. data/lib/acts_as_taggable_on/tags_helper.rb +2 -2
  24. data/lib/acts_as_taggable_on/utils.rb +34 -0
  25. data/lib/generators/acts_as_taggable_on/migration/migration_generator.rb +9 -2
  26. data/lib/generators/acts_as_taggable_on/migration/templates/active_record/migration.rb +3 -1
  27. data/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb +300 -54
  28. data/spec/acts_as_taggable_on/tag_list_spec.rb +84 -61
  29. data/spec/acts_as_taggable_on/tag_spec.rb +51 -13
  30. data/spec/acts_as_taggable_on/taggable_spec.rb +261 -34
  31. data/spec/acts_as_taggable_on/tagger_spec.rb +36 -15
  32. data/spec/acts_as_taggable_on/tagging_spec.rb +2 -5
  33. data/spec/acts_as_taggable_on/tags_helper_spec.rb +16 -0
  34. data/spec/acts_as_taggable_on/utils_spec.rb +21 -0
  35. data/spec/database.yml.sample +4 -2
  36. data/spec/generators/acts_as_taggable_on/migration/migration_generator_spec.rb +22 -0
  37. data/spec/models.rb +19 -1
  38. data/spec/schema.rb +18 -0
  39. data/spec/spec_helper.rb +30 -7
  40. data/uninstall.rb +1 -0
  41. metadata +137 -51
  42. data/VERSION +0 -1
  43. data/generators/acts_as_taggable_on_migration/acts_as_taggable_on_migration_generator.rb +0 -7
  44. data/generators/acts_as_taggable_on_migration/templates/migration.rb +0 -29
  45. data/lib/acts_as_taggable_on/acts_as_taggable_on.rb +0 -53
  46. data/lib/acts_as_taggable_on/compatibility/Gemfile +0 -8
  47. data/lib/acts_as_taggable_on/compatibility/active_record_backports.rb +0 -17
  48. data/lib/acts_as_taggable_on/compatibility/postgresql.rb +0 -44
  49. data/spec/database.yml +0 -17
@@ -8,11 +8,25 @@ describe "Acts As Taggable On" do
8
8
  it "should provide a class method 'taggable?' that is false for untaggable models" do
9
9
  UntaggableModel.should_not be_taggable
10
10
  end
11
+
12
+ describe "Taggable Method Generation To Preserve Order" do
13
+ before(:each) do
14
+ clean_database!
15
+ TaggableModel.tag_types = []
16
+ TaggableModel.preserve_tag_order = false
17
+ TaggableModel.acts_as_ordered_taggable_on(:ordered_tags)
18
+ @taggable = TaggableModel.new(:name => "Bob Jones")
19
+ end
20
+
21
+ it "should respond 'true' to preserve_tag_order?" do
22
+ @taggable.class.preserve_tag_order?.should be_true
23
+ end
24
+ end
11
25
 
12
26
  describe "Taggable Method Generation" do
13
27
  before(:each) do
14
28
  clean_database!
15
- TaggableModel.write_inheritable_attribute(:tag_types, [])
29
+ TaggableModel.tag_types = []
16
30
  TaggableModel.acts_as_taggable_on(:tags, :languages, :skills, :needs, :offerings)
17
31
  @taggable = TaggableModel.new(:name => "Bob Jones")
18
32
  end
@@ -28,10 +42,22 @@ describe "Acts As Taggable On" do
28
42
  it "should create an instance attribute for tag types" do
29
43
  @taggable.should respond_to(:tag_types)
30
44
  end
31
-
45
+
32
46
  it "should have all tag types" do
33
47
  @taggable.tag_types.should == [:tags, :languages, :skills, :needs, :offerings]
34
48
  end
49
+
50
+ it "should create a class attribute for preserve tag order" do
51
+ @taggable.class.should respond_to(:preserve_tag_order?)
52
+ end
53
+
54
+ it "should create an instance attribute for preserve tag order" do
55
+ @taggable.should respond_to(:preserve_tag_order?)
56
+ end
57
+
58
+ it "should respond 'false' to preserve_tag_order?" do
59
+ @taggable.class.preserve_tag_order?.should be_false
60
+ end
35
61
 
36
62
  it "should generate an association for each tag type" do
37
63
  @taggable.should respond_to(:tags, :skills, :languages)
@@ -45,7 +71,7 @@ describe "Acts As Taggable On" do
45
71
  @taggable.should respond_to(:tag_list, :skill_list, :language_list)
46
72
  @taggable.should respond_to(:tag_list=, :skill_list=, :language_list=)
47
73
  end
48
-
74
+
49
75
  it "should generate a tag_list accessor, that includes owned tags, for each tag type" do
50
76
  @taggable.should respond_to(:all_tags_list, :all_skills_list, :all_languages_list)
51
77
  end
@@ -57,17 +83,17 @@ describe "Acts As Taggable On" do
57
83
  @inherited_same = InheritingTaggableModel.new(:name => "inherited same")
58
84
  @inherited_different = AlteredInheritingTaggableModel.new(:name => "inherited different")
59
85
  end
60
-
86
+
61
87
  it "should pass on tag contexts to STI-inherited models" do
62
88
  @inherited_same.should respond_to(:tag_list, :skill_list, :language_list)
63
89
  @inherited_different.should respond_to(:tag_list, :skill_list, :language_list)
64
90
  end
65
-
91
+
66
92
  it "should have tag contexts added in altered STI models" do
67
93
  @inherited_different.should respond_to(:part_list)
68
94
  end
69
95
  end
70
-
96
+
71
97
  describe "Reloading" do
72
98
  it "should save a model instantiated by Model.find" do
73
99
  taggable = TaggableModel.create!(:name => "Taggable")
@@ -81,51 +107,121 @@ describe "Acts As Taggable On" do
81
107
  taggable1 = TaggableModel.create!(:name => "Taggable 1")
82
108
  taggable2 = TaggableModel.create!(:name => "Taggable 2")
83
109
  taggable3 = TaggableModel.create!(:name => "Taggable 3")
84
-
110
+
85
111
  taggable1.tag_list = "one, two"
86
112
  taggable1.save
87
-
113
+
88
114
  taggable2.tag_list = "three, four"
89
115
  taggable2.save
90
-
116
+
91
117
  taggable3.tag_list = "one, four"
92
118
  taggable3.save
93
-
119
+
94
120
  taggable1.find_related_tags.should include(taggable3)
95
121
  taggable1.find_related_tags.should_not include(taggable2)
96
122
  end
97
-
123
+
124
+ it "should find related objects based on tag names on context - non standard id" do
125
+ taggable1 = NonStandardIdTaggableModel.create!(:name => "Taggable 1")
126
+ taggable2 = NonStandardIdTaggableModel.create!(:name => "Taggable 2")
127
+ taggable3 = NonStandardIdTaggableModel.create!(:name => "Taggable 3")
128
+
129
+ taggable1.tag_list = "one, two"
130
+ taggable1.save
131
+
132
+ taggable2.tag_list = "three, four"
133
+ taggable2.save
134
+
135
+ taggable3.tag_list = "one, four"
136
+ taggable3.save
137
+
138
+ taggable1.find_related_tags.should include(taggable3)
139
+ taggable1.find_related_tags.should_not include(taggable2)
140
+ end
141
+
98
142
  it "should find other related objects based on tag names on context" do
99
143
  taggable1 = TaggableModel.create!(:name => "Taggable 1")
100
144
  taggable2 = OtherTaggableModel.create!(:name => "Taggable 2")
101
145
  taggable3 = OtherTaggableModel.create!(:name => "Taggable 3")
102
-
146
+
103
147
  taggable1.tag_list = "one, two"
104
148
  taggable1.save
105
-
149
+
106
150
  taggable2.tag_list = "three, four"
107
151
  taggable2.save
108
-
152
+
109
153
  taggable3.tag_list = "one, four"
110
154
  taggable3.save
111
-
155
+
112
156
  taggable1.find_related_tags_for(OtherTaggableModel).should include(taggable3)
113
157
  taggable1.find_related_tags_for(OtherTaggableModel).should_not include(taggable2)
114
158
  end
115
-
159
+
116
160
  it "should not include the object itself in the list of related objects" do
117
161
  taggable1 = TaggableModel.create!(:name => "Taggable 1")
118
162
  taggable2 = TaggableModel.create!(:name => "Taggable 2")
119
-
163
+
120
164
  taggable1.tag_list = "one"
121
165
  taggable1.save
122
-
166
+
123
167
  taggable2.tag_list = "one, two"
124
168
  taggable2.save
125
-
169
+
126
170
  taggable1.find_related_tags.should include(taggable2)
127
171
  taggable1.find_related_tags.should_not include(taggable1)
128
172
  end
173
+
174
+ it "should not include the object itself in the list of related objects - non standard id" do
175
+ taggable1 = NonStandardIdTaggableModel.create!(:name => "Taggable 1")
176
+ taggable2 = NonStandardIdTaggableModel.create!(:name => "Taggable 2")
177
+
178
+ taggable1.tag_list = "one"
179
+ taggable1.save
180
+
181
+ taggable2.tag_list = "one, two"
182
+ taggable2.save
183
+
184
+ taggable1.find_related_tags.should include(taggable2)
185
+ taggable1.find_related_tags.should_not include(taggable1)
186
+ end
187
+
188
+ context "Inherited Models" do
189
+ before do
190
+ @taggable1 = InheritingTaggableModel.create!(:name => "InheritingTaggable 1")
191
+ @taggable2 = InheritingTaggableModel.create!(:name => "InheritingTaggable 2")
192
+ @taggable3 = InheritingTaggableModel.create!(:name => "InheritingTaggable 3")
193
+ @taggable4 = TaggableModel.create!(:name => "Taggable 4")
194
+
195
+ @taggable1.tag_list = "one, two"
196
+ @taggable1.save
197
+
198
+ @taggable2.tag_list = "three, four"
199
+ @taggable2.save
200
+
201
+ @taggable3.tag_list = "one, four"
202
+ @taggable3.save
203
+
204
+ @taggable4.tag_list = "one, two, three, four"
205
+ @taggable4.save
206
+ end
207
+
208
+ it "should find related objects based on tag names on context" do
209
+ @taggable1.find_related_tags.should include(@taggable3)
210
+ @taggable1.find_related_tags.should_not include(@taggable2)
211
+ @taggable1.find_related_tags.should_not include(@taggable4)
212
+
213
+ @taggable1.find_related_tags_for(TaggableModel).should include(@taggable3)
214
+ @taggable1.find_related_tags_for(TaggableModel).should_not include(@taggable2)
215
+ @taggable1.find_related_tags_for(TaggableModel).should include(@taggable4)
216
+ end
217
+
218
+ it "should not include the object itself in the list of related objects" do
219
+ @taggable1.find_related_tags.should_not include(@taggable1)
220
+ @taggable1.find_related_tags_for(InheritingTaggableModel).should_not include(@taggable1)
221
+ @taggable1.find_related_tags_for(TaggableModel).should_not include(@taggable1)
222
+ end
223
+ end
224
+
129
225
  end
130
226
 
131
227
  describe "Matching Contexts" do
@@ -133,50 +229,95 @@ describe "Acts As Taggable On" do
133
229
  taggable1 = TaggableModel.create!(:name => "Taggable 1")
134
230
  taggable2 = TaggableModel.create!(:name => "Taggable 2")
135
231
  taggable3 = TaggableModel.create!(:name => "Taggable 3")
136
-
232
+
137
233
  taggable1.offering_list = "one, two"
138
234
  taggable1.save!
139
-
235
+
140
236
  taggable2.need_list = "one, two"
141
237
  taggable2.save!
142
-
238
+
143
239
  taggable3.offering_list = "one, two"
144
240
  taggable3.save!
145
-
241
+
146
242
  taggable1.find_matching_contexts(:offerings, :needs).should include(taggable2)
147
243
  taggable1.find_matching_contexts(:offerings, :needs).should_not include(taggable3)
148
244
  end
149
-
245
+
150
246
  it "should find other related objects with tags of matching contexts" do
151
247
  taggable1 = TaggableModel.create!(:name => "Taggable 1")
152
248
  taggable2 = OtherTaggableModel.create!(:name => "Taggable 2")
153
249
  taggable3 = OtherTaggableModel.create!(:name => "Taggable 3")
154
-
250
+
155
251
  taggable1.offering_list = "one, two"
156
252
  taggable1.save
157
-
253
+
158
254
  taggable2.need_list = "one, two"
159
255
  taggable2.save
160
-
256
+
161
257
  taggable3.offering_list = "one, two"
162
258
  taggable3.save
163
-
259
+
164
260
  taggable1.find_matching_contexts_for(OtherTaggableModel, :offerings, :needs).should include(taggable2)
165
261
  taggable1.find_matching_contexts_for(OtherTaggableModel, :offerings, :needs).should_not include(taggable3)
166
262
  end
167
-
168
- it "should not include the object itself in the list of related objects" do
263
+
264
+ it "should not include the object itself in the list of related objects with tags of matching contexts" do
169
265
  taggable1 = TaggableModel.create!(:name => "Taggable 1")
170
266
  taggable2 = TaggableModel.create!(:name => "Taggable 2")
171
-
172
- taggable1.tag_list = "one"
267
+
268
+ taggable1.offering_list = "one, two"
269
+ taggable1.need_list = "one, two"
173
270
  taggable1.save
174
-
175
- taggable2.tag_list = "one, two"
271
+
272
+ taggable2.need_list = "one, two"
176
273
  taggable2.save
177
-
178
- taggable1.find_related_tags.should include(taggable2)
179
- taggable1.find_related_tags.should_not include(taggable1)
274
+
275
+ taggable1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should include(taggable2)
276
+ taggable1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should_not include(taggable1)
277
+ end
278
+
279
+ context "Inherited Models" do
280
+ before do
281
+ @taggable1 = InheritingTaggableModel.create!(:name => "InheritingTaggable 1")
282
+ @taggable2 = InheritingTaggableModel.create!(:name => "InheritingTaggable 2")
283
+ @taggable3 = InheritingTaggableModel.create!(:name => "InheritingTaggable 3")
284
+ @taggable4 = InheritingTaggableModel.create!(:name => "InheritingTaggable 4")
285
+ @taggable5 = TaggableModel.create!(:name => "Taggable 5")
286
+
287
+ @taggable1.offering_list = "one, two"
288
+ @taggable1.need_list = "one, two"
289
+ @taggable1.save!
290
+
291
+ @taggable2.need_list = "one, two"
292
+ @taggable2.save!
293
+
294
+ @taggable3.offering_list = "one, two"
295
+ @taggable3.save!
296
+
297
+ @taggable4.tag_list = "one, two, three, four"
298
+ @taggable4.save!
299
+
300
+ @taggable5.need_list = "one, two"
301
+ @taggable5.save!
302
+ end
303
+
304
+ it "should find objects with tags of matching contexts" do
305
+ @taggable1.find_matching_contexts(:offerings, :needs).should include(@taggable2)
306
+ @taggable1.find_matching_contexts(:offerings, :needs).should_not include(@taggable3)
307
+ @taggable1.find_matching_contexts(:offerings, :needs).should_not include(@taggable4)
308
+ @taggable1.find_matching_contexts(:offerings, :needs).should_not include(@taggable5)
309
+
310
+ @taggable1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should include(@taggable2)
311
+ @taggable1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should_not include(@taggable3)
312
+ @taggable1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should_not include(@taggable4)
313
+ @taggable1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should include(@taggable5)
314
+ end
315
+
316
+ it "should not include the object itself in the list of related objects with tags of matching contexts" do
317
+ @taggable1.find_matching_contexts(:offerings, :needs).should_not include(@taggable1)
318
+ @taggable1.find_matching_contexts_for(InheritingTaggableModel, :offerings, :needs).should_not include(@taggable1)
319
+ @taggable1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should_not include(@taggable1)
320
+ end
180
321
  end
181
322
  end
182
323
 
@@ -208,55 +349,67 @@ describe "Acts As Taggable On" do
208
349
  }.should_not raise_error
209
350
  end
210
351
  end
211
-
352
+
212
353
  describe 'Caching' do
213
354
  before(:each) do
214
- @taggable = CachedModel.new(:name => "Bob Jones")
355
+ @taggable = CachedModel.new(:name => "Bob Jones")
356
+ @another_taggable = OtherCachedModel.new(:name => "John Smith")
215
357
  end
216
-
358
+
217
359
  it "should add saving of tag lists and cached tag lists to the instance" do
218
360
  @taggable.should respond_to(:save_cached_tag_list)
361
+ @another_taggable.should respond_to(:save_cached_tag_list)
362
+
219
363
  @taggable.should respond_to(:save_tags)
220
- end
364
+ end
365
+
366
+ it "should add cached tag lists to the instance if cached column is not present" do
367
+ TaggableModel.new(:name => "Art Kram").should_not respond_to(:save_cached_tag_list)
368
+ end
221
369
 
222
370
  it "should generate a cached column checker for each tag type" do
223
371
  CachedModel.should respond_to(:caching_tag_list?)
224
- end
225
-
372
+ OtherCachedModel.should respond_to(:caching_language_list?)
373
+ end
374
+
226
375
  it 'should not have cached tags' do
227
- @taggable.cached_tag_list.should be_blank
376
+ @taggable.cached_tag_list.should be_blank
377
+ @another_taggable.cached_language_list.should be_blank
228
378
  end
229
-
379
+
230
380
  it 'should cache tags' do
231
381
  @taggable.update_attributes(:tag_list => 'awesome, epic')
232
382
  @taggable.cached_tag_list.should == 'awesome, epic'
383
+
384
+ @another_taggable.update_attributes(:language_list => 'ruby, .net')
385
+ @another_taggable.cached_language_list.should == 'ruby, .net'
233
386
  end
234
-
387
+
235
388
  it 'should keep the cache' do
236
389
  @taggable.update_attributes(:tag_list => 'awesome, epic')
237
- @taggable = CachedModel.find(@taggable)
390
+ @taggable = CachedModel.find(@taggable)
238
391
  @taggable.save!
239
- @taggable.cached_tag_list.should == 'awesome, epic'
392
+ @taggable.cached_tag_list.should == 'awesome, epic'
240
393
  end
241
-
394
+
242
395
  it 'should update the cache' do
243
396
  @taggable.update_attributes(:tag_list => 'awesome, epic')
244
397
  @taggable.update_attributes(:tag_list => 'awesome')
245
- @taggable.cached_tag_list.should == 'awesome'
398
+ @taggable.cached_tag_list.should == 'awesome'
246
399
  end
247
-
400
+
248
401
  it 'should remove the cache' do
249
402
  @taggable.update_attributes(:tag_list => 'awesome, epic')
250
403
  @taggable.update_attributes(:tag_list => '')
251
- @taggable.cached_tag_list.should be_blank
404
+ @taggable.cached_tag_list.should be_blank
252
405
  end
253
-
406
+
254
407
  it 'should have a tag list' do
255
408
  @taggable.update_attributes(:tag_list => 'awesome, epic')
256
409
  @taggable = CachedModel.find(@taggable.id)
257
410
  @taggable.tag_list.sort.should == %w(awesome epic).sort
258
411
  end
259
-
412
+
260
413
  it 'should keep the tag list' do
261
414
  @taggable.update_attributes(:tag_list => 'awesome, epic')
262
415
  @taggable = CachedModel.find(@taggable.id)
@@ -265,4 +418,97 @@ describe "Acts As Taggable On" do
265
418
  end
266
419
  end
267
420
 
421
+ context 'when tagging context ends in an "s" when singular (ex. "status", "glass", etc.)' do
422
+ describe 'caching' do
423
+ before { @taggable = OtherCachedModel.new(:name => "John Smith") }
424
+ subject { @taggable }
425
+
426
+ it { should respond_to(:save_cached_tag_list) }
427
+ its(:cached_language_list) { should be_blank }
428
+ its(:cached_status_list) { should be_blank }
429
+ its(:cached_glass_list) { should be_blank }
430
+
431
+ context 'language taggings cache after update' do
432
+ before { @taggable.update_attributes(:language_list => 'ruby, .net') }
433
+ subject { @taggable }
434
+
435
+ its(:language_list) { should == ['ruby', '.net']}
436
+ its(:cached_language_list) { should == 'ruby, .net' } # passes
437
+ its(:instance_variables) { should include((RUBY_VERSION < '1.9' ? '@language_list' : :@language_list)) }
438
+ end
439
+
440
+ context 'status taggings cache after update' do
441
+ before { @taggable.update_attributes(:status_list => 'happy, married') }
442
+ subject { @taggable }
443
+
444
+ its(:status_list) { should == ['happy', 'married'] }
445
+ its(:cached_status_list) { should == 'happy, married' } # fails
446
+ its(:cached_status_list) { should_not == '' } # fails, is blank
447
+ its(:instance_variables) { should include((RUBY_VERSION < '1.9' ? '@status_list' : :@status_list)) }
448
+ its(:instance_variables) { should_not include((RUBY_VERSION < '1.9' ? '@statu_list' : :@statu_list)) } # fails, note: one "s"
449
+
450
+ end
451
+
452
+ context 'glass taggings cache after update' do
453
+ before do
454
+ @taggable.update_attributes(:glass_list => 'rectangle, aviator')
455
+ end
456
+
457
+ subject { @taggable }
458
+ its(:glass_list) { should == ['rectangle', 'aviator'] }
459
+ its(:cached_glass_list) { should == 'rectangle, aviator' } # fails
460
+ its(:cached_glass_list) { should_not == '' } # fails, is blank
461
+ if RUBY_VERSION < '1.9'
462
+ its(:instance_variables) { should include('@glass_list') }
463
+ its(:instance_variables) { should_not include('@glas_list') } # fails, note: one "s"
464
+ else
465
+ its(:instance_variables) { should include(:@glass_list) }
466
+ its(:instance_variables) { should_not include(:@glas_list) } # fails, note: one "s"
467
+ end
468
+
469
+ end
470
+ end
471
+ end
472
+
473
+ describe "taggings" do
474
+ before(:each) do
475
+ @taggable = TaggableModel.new(:name => "Art Kram")
476
+ end
477
+
478
+ it 'should return [] taggings' do
479
+ @taggable.taggings.should == []
480
+ end
481
+ end
482
+
483
+ describe "@@remove_unused_tags" do
484
+ before do
485
+ @taggable = TaggableModel.create(:name => "Bob Jones")
486
+ @tag = ActsAsTaggableOn::Tag.create(:name => "awesome")
487
+
488
+ @tagging = ActsAsTaggableOn::Tagging.create(:taggable => @taggable, :tag => @tag, :context => 'tags')
489
+ end
490
+
491
+ context "if set to true" do
492
+ before do
493
+ ActsAsTaggableOn.remove_unused_tags = true
494
+ end
495
+
496
+ it "should remove unused tags after removing taggings" do
497
+ @tagging.destroy
498
+ ActsAsTaggableOn::Tag.find_by_name("awesome").should be_nil
499
+ end
500
+ end
501
+
502
+ context "if set to false" do
503
+ before do
504
+ ActsAsTaggableOn.remove_unused_tags = false
505
+ end
506
+
507
+ it "should not remove unused tags after removing taggings" do
508
+ @tagging.destroy
509
+ ActsAsTaggableOn::Tag.find_by_name("awesome").should == @tag
510
+ end
511
+ end
512
+ end
513
+
268
514
  end
@@ -1,70 +1,93 @@
1
1
  require File.expand_path('../../spec_helper', __FILE__)
2
2
 
3
3
  describe ActsAsTaggableOn::TagList do
4
- before(:each) do
5
- @tag_list = ActsAsTaggableOn::TagList.new("awesome","radical")
6
- end
7
-
8
- it "should be an array" do
9
- @tag_list.is_a?(Array).should be_true
10
- end
11
-
12
- it "should be able to be add a new tag word" do
13
- @tag_list.add("cool")
14
- @tag_list.include?("cool").should be_true
15
- end
16
-
17
- it "should be able to add delimited lists of words" do
18
- @tag_list.add("cool, wicked", :parse => true)
19
- @tag_list.include?("cool").should be_true
20
- @tag_list.include?("wicked").should be_true
21
- end
22
-
23
- it "should be able to add delimited list of words with quoted delimiters" do
24
- @tag_list.add("'cool, wicked', \"really cool, really wicked\"", :parse => true)
25
- @tag_list.include?("cool, wicked").should be_true
26
- @tag_list.include?("really cool, really wicked").should be_true
27
- end
28
-
29
- it "should be able to handle other uses of quotation marks correctly" do
30
- @tag_list.add("john's cool car, mary's wicked toy", :parse => true)
31
- @tag_list.include?("john's cool car").should be_true
32
- @tag_list.include?("mary's wicked toy").should be_true
33
- end
34
-
35
- it "should be able to add an array of words" do
36
- @tag_list.add(["cool", "wicked"], :parse => true)
37
- @tag_list.include?("cool").should be_true
38
- @tag_list.include?("wicked").should be_true
39
- end
40
-
41
- it "should be able to remove words" do
42
- @tag_list.remove("awesome")
43
- @tag_list.include?("awesome").should be_false
44
- end
45
-
46
- it "should be able to remove delimited lists of words" do
47
- @tag_list.remove("awesome, radical", :parse => true)
48
- @tag_list.should be_empty
4
+ let(:tag_list) { ActsAsTaggableOn::TagList.new("awesome","radical") }
5
+
6
+ it { should be_kind_of Array }
7
+
8
+ it "#from should return empty array if empty array is passed" do
9
+ ActsAsTaggableOn::TagList.from([]).should be_empty
49
10
  end
50
-
51
- it "should be able to remove an array of words" do
52
- @tag_list.remove(["awesome", "radical"], :parse => true)
53
- @tag_list.should be_empty
11
+
12
+ describe "#add" do
13
+ it "should be able to be add a new tag word" do
14
+ tag_list.add("cool")
15
+ tag_list.include?("cool").should be_true
16
+ end
17
+
18
+ it "should be able to add delimited lists of words" do
19
+ tag_list.add("cool, wicked", :parse => true)
20
+ tag_list.should include("cool", "wicked")
21
+ end
22
+
23
+ it "should be able to add delimited list of words with quoted delimiters" do
24
+ tag_list.add("'cool, wicked', \"really cool, really wicked\"", :parse => true)
25
+ tag_list.should include("cool, wicked", "really cool, really wicked")
26
+ end
27
+
28
+ it "should be able to handle other uses of quotation marks correctly" do
29
+ tag_list.add("john's cool car, mary's wicked toy", :parse => true)
30
+ tag_list.should include("john's cool car", "mary's wicked toy")
31
+ end
32
+
33
+ it "should be able to add an array of words" do
34
+ tag_list.add(["cool", "wicked"], :parse => true)
35
+ tag_list.should include("cool", "wicked")
36
+ end
37
+
38
+ it "should quote escape tags with commas in them" do
39
+ tag_list.add("cool","rad,bodacious")
40
+ tag_list.to_s.should == "awesome, radical, cool, \"rad,bodacious\""
41
+ end
42
+
54
43
  end
55
-
56
- it "should give a delimited list of words when converted to string" do
57
- @tag_list.to_s.should == "awesome, radical"
44
+
45
+ describe "#remove" do
46
+ it "should be able to remove words" do
47
+ tag_list.remove("awesome")
48
+ tag_list.should_not include("awesome")
49
+ end
50
+
51
+ it "should be able to remove delimited lists of words" do
52
+ tag_list.remove("awesome, radical", :parse => true)
53
+ tag_list.should be_empty
54
+ end
55
+
56
+ it "should be able to remove an array of words" do
57
+ tag_list.remove(["awesome", "radical"], :parse => true)
58
+ tag_list.should be_empty
59
+ end
58
60
  end
59
-
60
- it "should quote escape tags with commas in them" do
61
- @tag_list.add("cool","rad,bodacious")
62
- @tag_list.to_s.should == "awesome, radical, cool, \"rad,bodacious\""
61
+
62
+ describe "#to_s" do
63
+ it "should give a delimited list of words when converted to string" do
64
+ tag_list.to_s.should == "awesome, radical"
65
+ end
66
+
67
+ it "should be able to call to_s on a frozen tag list" do
68
+ tag_list.freeze
69
+ lambda { tag_list.add("cool","rad,bodacious") }.should raise_error
70
+ lambda { tag_list.to_s }.should_not raise_error
71
+ end
63
72
  end
64
-
65
- it "should be able to call to_s on a frozen tag list" do
66
- @tag_list.freeze
67
- lambda { @tag_list.add("cool","rad,bodacious") }.should raise_error
68
- lambda { @tag_list.to_s }.should_not raise_error
73
+
74
+ describe "cleaning" do
75
+ it "should parameterize if force_parameterize is set to true" do
76
+ ActsAsTaggableOn.force_parameterize = true
77
+ tag_list = ActsAsTaggableOn::TagList.new("awesome()","radical)(cc")
78
+
79
+ tag_list.to_s.should == "awesome, radical-cc"
80
+ ActsAsTaggableOn.force_parameterize = false
81
+ end
82
+
83
+ it "should lowercase if force_lowercase is set to true" do
84
+ ActsAsTaggableOn.force_lowercase = true
85
+
86
+ tag_list = ActsAsTaggableOn::TagList.new("aweSomE","RaDicaL")
87
+ tag_list.to_s.should == "awesome, radical"
88
+
89
+ ActsAsTaggableOn.force_lowercase = false
90
+ end
91
+
69
92
  end
70
93
  end