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.
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.travis.yml +9 -0
- data/CHANGELOG +10 -0
- data/Gemfile +2 -9
- data/Guardfile +5 -0
- data/README.rdoc +89 -66
- data/Rakefile +9 -55
- data/acts-as-taggable-on.gemspec +28 -0
- data/lib/acts-as-taggable-on/version.rb +4 -0
- data/lib/acts-as-taggable-on.rb +33 -4
- data/lib/acts_as_taggable_on/acts_as_taggable_on/cache.rb +4 -4
- data/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb +38 -43
- data/lib/acts_as_taggable_on/acts_as_taggable_on/core.rb +146 -38
- data/lib/acts_as_taggable_on/acts_as_taggable_on/dirty.rb +37 -0
- data/lib/acts_as_taggable_on/acts_as_taggable_on/ownership.rb +36 -11
- data/lib/acts_as_taggable_on/acts_as_taggable_on/related.rb +23 -15
- data/lib/acts_as_taggable_on/tag.rb +16 -13
- data/lib/acts_as_taggable_on/tag_list.rb +13 -12
- data/lib/acts_as_taggable_on/taggable.rb +102 -0
- data/lib/acts_as_taggable_on/{acts_as_tagger.rb → tagger.rb} +3 -3
- data/lib/acts_as_taggable_on/tagging.rb +12 -2
- data/lib/acts_as_taggable_on/tags_helper.rb +2 -2
- data/lib/acts_as_taggable_on/utils.rb +34 -0
- data/lib/generators/acts_as_taggable_on/migration/migration_generator.rb +9 -2
- data/lib/generators/acts_as_taggable_on/migration/templates/active_record/migration.rb +3 -1
- data/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb +300 -54
- data/spec/acts_as_taggable_on/tag_list_spec.rb +84 -61
- data/spec/acts_as_taggable_on/tag_spec.rb +51 -13
- data/spec/acts_as_taggable_on/taggable_spec.rb +261 -34
- data/spec/acts_as_taggable_on/tagger_spec.rb +36 -15
- data/spec/acts_as_taggable_on/tagging_spec.rb +2 -5
- data/spec/acts_as_taggable_on/tags_helper_spec.rb +16 -0
- data/spec/acts_as_taggable_on/utils_spec.rb +21 -0
- data/spec/database.yml.sample +4 -2
- data/spec/generators/acts_as_taggable_on/migration/migration_generator_spec.rb +22 -0
- data/spec/models.rb +19 -1
- data/spec/schema.rb +18 -0
- data/spec/spec_helper.rb +30 -7
- data/uninstall.rb +1 -0
- metadata +137 -51
- data/VERSION +0 -1
- data/generators/acts_as_taggable_on_migration/acts_as_taggable_on_migration_generator.rb +0 -7
- data/generators/acts_as_taggable_on_migration/templates/migration.rb +0 -29
- data/lib/acts_as_taggable_on/acts_as_taggable_on.rb +0 -53
- data/lib/acts_as_taggable_on/compatibility/Gemfile +0 -8
- data/lib/acts_as_taggable_on/compatibility/active_record_backports.rb +0 -17
- data/lib/acts_as_taggable_on/compatibility/postgresql.rb +0 -44
- 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.
|
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.
|
267
|
+
|
268
|
+
taggable1.offering_list = "one, two"
|
269
|
+
taggable1.need_list = "one, two"
|
173
270
|
taggable1.save
|
174
|
-
|
175
|
-
taggable2.
|
271
|
+
|
272
|
+
taggable2.need_list = "one, two"
|
176
273
|
taggable2.save
|
177
|
-
|
178
|
-
taggable1.
|
179
|
-
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
|
-
|
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
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
it "should
|
9
|
-
|
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
|
-
|
52
|
-
|
53
|
-
|
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
|
-
|
57
|
-
|
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
|
-
|
61
|
-
|
62
|
-
|
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
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
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
|