acts-as-taggable-on 2.0.6 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
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