acts-as-taggable-on 2.1.1 → 2.2.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 (30) hide show
  1. data/.gitignore +1 -0
  2. data/.travis.yml +1 -2
  3. data/README.rdoc +27 -50
  4. data/acts-as-taggable-on.gemspec +4 -3
  5. data/lib/acts-as-taggable-on.rb +0 -4
  6. data/lib/acts-as-taggable-on/version.rb +1 -1
  7. data/lib/acts_as_taggable_on/acts_as_taggable_on.rb +4 -13
  8. data/lib/acts_as_taggable_on/acts_as_taggable_on/cache.rb +1 -1
  9. data/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb +1 -1
  10. data/lib/acts_as_taggable_on/acts_as_taggable_on/core.rb +29 -17
  11. data/lib/acts_as_taggable_on/acts_as_taggable_on/related.rb +15 -15
  12. data/lib/acts_as_taggable_on/tag.rb +12 -13
  13. data/lib/acts_as_taggable_on/tagging.rb +0 -2
  14. data/lib/acts_as_taggable_on/utils.rb +7 -8
  15. data/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb +228 -61
  16. data/spec/acts_as_taggable_on/tag_list_spec.rb +4 -0
  17. data/spec/acts_as_taggable_on/tag_spec.rb +11 -15
  18. data/spec/acts_as_taggable_on/taggable_spec.rb +89 -27
  19. data/spec/acts_as_taggable_on/tagger_spec.rb +14 -0
  20. data/spec/acts_as_taggable_on/utils_spec.rb +2 -3
  21. data/spec/database.yml.sample +1 -1
  22. data/spec/generators/acts_as_taggable_on/migration/migration_generator_spec.rb +22 -0
  23. data/spec/models.rb +11 -2
  24. data/spec/schema.rb +7 -0
  25. data/spec/spec_helper.rb +1 -0
  26. metadata +95 -122
  27. data/generators/acts_as_taggable_on_migration/acts_as_taggable_on_migration_generator.rb +0 -7
  28. data/generators/acts_as_taggable_on_migration/templates/migration.rb +0 -29
  29. data/lib/acts_as_taggable_on/compatibility/Gemfile +0 -8
  30. data/lib/acts_as_taggable_on/compatibility/active_record_backports.rb +0 -21
@@ -1,8 +1,7 @@
1
1
  module ActsAsTaggableOn
2
2
  class Tag < ::ActiveRecord::Base
3
- include ActsAsTaggableOn::ActiveRecord::Backports if ::ActiveRecord::VERSION::MAJOR < 3
4
3
  include ActsAsTaggableOn::Utils
5
-
4
+
6
5
  attr_accessible :name
7
6
 
8
7
  ### ASSOCIATIONS:
@@ -15,21 +14,21 @@ module ActsAsTaggableOn
15
14
  validates_uniqueness_of :name
16
15
 
17
16
  ### SCOPES:
18
-
17
+
19
18
  def self.named(name)
20
- where(["name #{like_operator} ?", escape_like(name)])
19
+ where(["name #{like_operator} ? ESCAPE '!'", escape_like(name)])
21
20
  end
22
-
21
+
23
22
  def self.named_any(list)
24
- where(list.map { |tag| sanitize_sql(["name #{like_operator} ?", escape_like(tag.to_s)]) }.join(" OR "))
23
+ where(list.map { |tag| sanitize_sql(["name #{like_operator} ? ESCAPE '!'", escape_like(tag.to_s)]) }.join(" OR "))
25
24
  end
26
-
25
+
27
26
  def self.named_like(name)
28
- where(["name #{like_operator} ?", "%#{escape_like(name)}%"])
27
+ where(["name #{like_operator} ? ESCAPE '!'", "%#{escape_like(name)}%"])
29
28
  end
30
29
 
31
30
  def self.named_like_any(list)
32
- where(list.map { |tag| sanitize_sql(["name #{like_operator} ?", "%#{escape_like(tag.to_s)}%"]) }.join(" OR "))
31
+ where(list.map { |tag| sanitize_sql(["name #{like_operator} ? ESCAPE '!'", "%#{escape_like(tag.to_s)}%"]) }.join(" OR "))
33
32
  end
34
33
 
35
34
  ### CLASS METHODS:
@@ -44,7 +43,7 @@ module ActsAsTaggableOn
44
43
  return [] if list.empty?
45
44
 
46
45
  existing_tags = Tag.named_any(list).all
47
- new_tag_names = list.reject do |name|
46
+ new_tag_names = list.reject do |name|
48
47
  name = comparable_name(name)
49
48
  existing_tags.any? { |tag| comparable_name(tag.name) == name }
50
49
  end
@@ -66,13 +65,13 @@ module ActsAsTaggableOn
66
65
  def count
67
66
  read_attribute(:count).to_i
68
67
  end
69
-
68
+
70
69
  def safe_name
71
70
  name.gsub(/[^a-zA-Z0-9]/, '')
72
71
  end
73
-
72
+
74
73
  class << self
75
- private
74
+ private
76
75
  def comparable_name(str)
77
76
  RUBY_VERSION >= "1.9" ? str.downcase : str.mb_chars.downcase
78
77
  end
@@ -1,7 +1,5 @@
1
1
  module ActsAsTaggableOn
2
2
  class Tagging < ::ActiveRecord::Base #:nodoc:
3
- include ActsAsTaggableOn::ActiveRecord::Backports if ::ActiveRecord::VERSION::MAJOR < 3
4
-
5
3
  attr_accessible :tag,
6
4
  :tag_id,
7
5
  :context,
@@ -1,29 +1,28 @@
1
1
  module ActsAsTaggableOn
2
2
  module Utils
3
3
  def self.included(base)
4
-
4
+
5
5
  base.send :include, ActsAsTaggableOn::Utils::OverallMethods
6
- base.extend ActsAsTaggableOn::Utils::OverallMethods
6
+ base.extend ActsAsTaggableOn::Utils::OverallMethods
7
7
  end
8
8
 
9
9
  module OverallMethods
10
10
  def using_postgresql?
11
11
  ::ActiveRecord::Base.connection && ::ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
12
12
  end
13
-
13
+
14
14
  def using_sqlite?
15
15
  ::ActiveRecord::Base.connection && ::ActiveRecord::Base.connection.adapter_name == 'SQLite'
16
- end
17
-
16
+ end
17
+
18
18
  private
19
19
  def like_operator
20
20
  using_postgresql? ? 'ILIKE' : 'LIKE'
21
21
  end
22
-
22
+
23
23
  # escape _ and % characters in strings, since these are wildcards in SQL.
24
24
  def escape_like(str)
25
- return str if using_sqlite? # skip escaping for SQLite
26
- str.to_s.gsub("_", "\\\_").gsub("%", "\\\%")
25
+ str.gsub(/[!%_]/){ |x| '!' + x }
27
26
  end
28
27
  end
29
28
 
@@ -12,7 +12,7 @@ describe "Acts As Taggable On" do
12
12
  describe "Taggable Method Generation" do
13
13
  before(:each) do
14
14
  clean_database!
15
- RAILS_3 ? TaggableModel.tag_types = [] : TaggableModel.write_inheritable_attribute(:tag_types, [])
15
+ TaggableModel.tag_types = []
16
16
  TaggableModel.acts_as_taggable_on(:tags, :languages, :skills, :needs, :offerings)
17
17
  @taggable = TaggableModel.new(:name => "Bob Jones")
18
18
  end
@@ -28,7 +28,7 @@ describe "Acts As Taggable On" do
28
28
  it "should create an instance attribute for tag types" do
29
29
  @taggable.should respond_to(:tag_types)
30
30
  end
31
-
31
+
32
32
  it "should have all tag types" do
33
33
  @taggable.tag_types.should == [:tags, :languages, :skills, :needs, :offerings]
34
34
  end
@@ -45,7 +45,7 @@ describe "Acts As Taggable On" do
45
45
  @taggable.should respond_to(:tag_list, :skill_list, :language_list)
46
46
  @taggable.should respond_to(:tag_list=, :skill_list=, :language_list=)
47
47
  end
48
-
48
+
49
49
  it "should generate a tag_list accessor, that includes owned tags, for each tag type" do
50
50
  @taggable.should respond_to(:all_tags_list, :all_skills_list, :all_languages_list)
51
51
  end
@@ -57,17 +57,17 @@ describe "Acts As Taggable On" do
57
57
  @inherited_same = InheritingTaggableModel.new(:name => "inherited same")
58
58
  @inherited_different = AlteredInheritingTaggableModel.new(:name => "inherited different")
59
59
  end
60
-
60
+
61
61
  it "should pass on tag contexts to STI-inherited models" do
62
62
  @inherited_same.should respond_to(:tag_list, :skill_list, :language_list)
63
63
  @inherited_different.should respond_to(:tag_list, :skill_list, :language_list)
64
64
  end
65
-
65
+
66
66
  it "should have tag contexts added in altered STI models" do
67
67
  @inherited_different.should respond_to(:part_list)
68
68
  end
69
69
  end
70
-
70
+
71
71
  describe "Reloading" do
72
72
  it "should save a model instantiated by Model.find" do
73
73
  taggable = TaggableModel.create!(:name => "Taggable")
@@ -81,51 +81,121 @@ describe "Acts As Taggable On" do
81
81
  taggable1 = TaggableModel.create!(:name => "Taggable 1")
82
82
  taggable2 = TaggableModel.create!(:name => "Taggable 2")
83
83
  taggable3 = TaggableModel.create!(:name => "Taggable 3")
84
-
84
+
85
+ taggable1.tag_list = "one, two"
86
+ taggable1.save
87
+
88
+ taggable2.tag_list = "three, four"
89
+ taggable2.save
90
+
91
+ taggable3.tag_list = "one, four"
92
+ taggable3.save
93
+
94
+ taggable1.find_related_tags.should include(taggable3)
95
+ taggable1.find_related_tags.should_not include(taggable2)
96
+ end
97
+
98
+ it "should find related objects based on tag names on context - non standard id" do
99
+ taggable1 = NonStandardIdTaggableModel.create!(:name => "Taggable 1")
100
+ taggable2 = NonStandardIdTaggableModel.create!(:name => "Taggable 2")
101
+ taggable3 = NonStandardIdTaggableModel.create!(:name => "Taggable 3")
102
+
85
103
  taggable1.tag_list = "one, two"
86
104
  taggable1.save
87
-
105
+
88
106
  taggable2.tag_list = "three, four"
89
107
  taggable2.save
90
-
108
+
91
109
  taggable3.tag_list = "one, four"
92
110
  taggable3.save
93
-
111
+
94
112
  taggable1.find_related_tags.should include(taggable3)
95
113
  taggable1.find_related_tags.should_not include(taggable2)
96
114
  end
97
-
115
+
98
116
  it "should find other related objects based on tag names on context" do
99
117
  taggable1 = TaggableModel.create!(:name => "Taggable 1")
100
118
  taggable2 = OtherTaggableModel.create!(:name => "Taggable 2")
101
119
  taggable3 = OtherTaggableModel.create!(:name => "Taggable 3")
102
-
120
+
103
121
  taggable1.tag_list = "one, two"
104
122
  taggable1.save
105
-
123
+
106
124
  taggable2.tag_list = "three, four"
107
125
  taggable2.save
108
-
126
+
109
127
  taggable3.tag_list = "one, four"
110
128
  taggable3.save
111
-
129
+
112
130
  taggable1.find_related_tags_for(OtherTaggableModel).should include(taggable3)
113
131
  taggable1.find_related_tags_for(OtherTaggableModel).should_not include(taggable2)
114
132
  end
115
-
133
+
116
134
  it "should not include the object itself in the list of related objects" do
117
135
  taggable1 = TaggableModel.create!(:name => "Taggable 1")
118
136
  taggable2 = TaggableModel.create!(:name => "Taggable 2")
119
-
137
+
120
138
  taggable1.tag_list = "one"
121
139
  taggable1.save
122
-
140
+
123
141
  taggable2.tag_list = "one, two"
124
142
  taggable2.save
125
-
143
+
126
144
  taggable1.find_related_tags.should include(taggable2)
127
145
  taggable1.find_related_tags.should_not include(taggable1)
128
146
  end
147
+
148
+ it "should not include the object itself in the list of related objects - non standard id" do
149
+ taggable1 = NonStandardIdTaggableModel.create!(:name => "Taggable 1")
150
+ taggable2 = NonStandardIdTaggableModel.create!(:name => "Taggable 2")
151
+
152
+ taggable1.tag_list = "one"
153
+ taggable1.save
154
+
155
+ taggable2.tag_list = "one, two"
156
+ taggable2.save
157
+
158
+ taggable1.find_related_tags.should include(taggable2)
159
+ taggable1.find_related_tags.should_not include(taggable1)
160
+ end
161
+
162
+ context "Inherited Models" do
163
+ before do
164
+ @taggable1 = InheritingTaggableModel.create!(:name => "InheritingTaggable 1")
165
+ @taggable2 = InheritingTaggableModel.create!(:name => "InheritingTaggable 2")
166
+ @taggable3 = InheritingTaggableModel.create!(:name => "InheritingTaggable 3")
167
+ @taggable4 = TaggableModel.create!(:name => "Taggable 4")
168
+
169
+ @taggable1.tag_list = "one, two"
170
+ @taggable1.save
171
+
172
+ @taggable2.tag_list = "three, four"
173
+ @taggable2.save
174
+
175
+ @taggable3.tag_list = "one, four"
176
+ @taggable3.save
177
+
178
+ @taggable4.tag_list = "one, two, three, four"
179
+ @taggable4.save
180
+ end
181
+
182
+ it "should find related objects based on tag names on context" do
183
+ @taggable1.find_related_tags.should include(@taggable3)
184
+ @taggable1.find_related_tags.should_not include(@taggable2)
185
+ @taggable1.find_related_tags.should_not include(@taggable4)
186
+
187
+ @taggable1.find_related_tags_for(TaggableModel).should include(@taggable3)
188
+ @taggable1.find_related_tags_for(TaggableModel).should_not include(@taggable2)
189
+ @taggable1.find_related_tags_for(TaggableModel).should include(@taggable4)
190
+ end
191
+
192
+ it "should not include the object itself in the list of related objects" do
193
+ @taggable1.find_related_tags.should_not include(@taggable1)
194
+ @taggable1.find_related_tags_for(InheritingTaggableModel).should_not include(@taggable1)
195
+ @taggable1.find_related_tags_for(TaggableModel).should_not include(@taggable1)
196
+ end
197
+ end
198
+
129
199
  end
130
200
 
131
201
  describe "Matching Contexts" do
@@ -133,50 +203,95 @@ describe "Acts As Taggable On" do
133
203
  taggable1 = TaggableModel.create!(:name => "Taggable 1")
134
204
  taggable2 = TaggableModel.create!(:name => "Taggable 2")
135
205
  taggable3 = TaggableModel.create!(:name => "Taggable 3")
136
-
206
+
137
207
  taggable1.offering_list = "one, two"
138
208
  taggable1.save!
139
-
209
+
140
210
  taggable2.need_list = "one, two"
141
211
  taggable2.save!
142
-
212
+
143
213
  taggable3.offering_list = "one, two"
144
214
  taggable3.save!
145
-
215
+
146
216
  taggable1.find_matching_contexts(:offerings, :needs).should include(taggable2)
147
217
  taggable1.find_matching_contexts(:offerings, :needs).should_not include(taggable3)
148
218
  end
149
-
219
+
150
220
  it "should find other related objects with tags of matching contexts" do
151
221
  taggable1 = TaggableModel.create!(:name => "Taggable 1")
152
222
  taggable2 = OtherTaggableModel.create!(:name => "Taggable 2")
153
223
  taggable3 = OtherTaggableModel.create!(:name => "Taggable 3")
154
-
224
+
155
225
  taggable1.offering_list = "one, two"
156
226
  taggable1.save
157
-
227
+
158
228
  taggable2.need_list = "one, two"
159
229
  taggable2.save
160
-
230
+
161
231
  taggable3.offering_list = "one, two"
162
232
  taggable3.save
163
-
233
+
164
234
  taggable1.find_matching_contexts_for(OtherTaggableModel, :offerings, :needs).should include(taggable2)
165
235
  taggable1.find_matching_contexts_for(OtherTaggableModel, :offerings, :needs).should_not include(taggable3)
166
236
  end
167
-
168
- it "should not include the object itself in the list of related objects" do
237
+
238
+ it "should not include the object itself in the list of related objects with tags of matching contexts" do
169
239
  taggable1 = TaggableModel.create!(:name => "Taggable 1")
170
240
  taggable2 = TaggableModel.create!(:name => "Taggable 2")
171
-
172
- taggable1.tag_list = "one"
241
+
242
+ taggable1.offering_list = "one, two"
243
+ taggable1.need_list = "one, two"
173
244
  taggable1.save
174
-
175
- taggable2.tag_list = "one, two"
245
+
246
+ taggable2.need_list = "one, two"
176
247
  taggable2.save
177
-
178
- taggable1.find_related_tags.should include(taggable2)
179
- taggable1.find_related_tags.should_not include(taggable1)
248
+
249
+ taggable1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should include(taggable2)
250
+ taggable1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should_not include(taggable1)
251
+ end
252
+
253
+ context "Inherited Models" do
254
+ before do
255
+ @taggable1 = InheritingTaggableModel.create!(:name => "InheritingTaggable 1")
256
+ @taggable2 = InheritingTaggableModel.create!(:name => "InheritingTaggable 2")
257
+ @taggable3 = InheritingTaggableModel.create!(:name => "InheritingTaggable 3")
258
+ @taggable4 = InheritingTaggableModel.create!(:name => "InheritingTaggable 4")
259
+ @taggable5 = TaggableModel.create!(:name => "Taggable 5")
260
+
261
+ @taggable1.offering_list = "one, two"
262
+ @taggable1.need_list = "one, two"
263
+ @taggable1.save!
264
+
265
+ @taggable2.need_list = "one, two"
266
+ @taggable2.save!
267
+
268
+ @taggable3.offering_list = "one, two"
269
+ @taggable3.save!
270
+
271
+ @taggable4.tag_list = "one, two, three, four"
272
+ @taggable4.save!
273
+
274
+ @taggable5.need_list = "one, two"
275
+ @taggable5.save!
276
+ end
277
+
278
+ it "should find objects with tags of matching contexts" do
279
+ @taggable1.find_matching_contexts(:offerings, :needs).should include(@taggable2)
280
+ @taggable1.find_matching_contexts(:offerings, :needs).should_not include(@taggable3)
281
+ @taggable1.find_matching_contexts(:offerings, :needs).should_not include(@taggable4)
282
+ @taggable1.find_matching_contexts(:offerings, :needs).should_not include(@taggable5)
283
+
284
+ @taggable1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should include(@taggable2)
285
+ @taggable1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should_not include(@taggable3)
286
+ @taggable1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should_not include(@taggable4)
287
+ @taggable1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should include(@taggable5)
288
+ end
289
+
290
+ it "should not include the object itself in the list of related objects with tags of matching contexts" do
291
+ @taggable1.find_matching_contexts(:offerings, :needs).should_not include(@taggable1)
292
+ @taggable1.find_matching_contexts_for(InheritingTaggableModel, :offerings, :needs).should_not include(@taggable1)
293
+ @taggable1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should_not include(@taggable1)
294
+ end
180
295
  end
181
296
  end
182
297
 
@@ -208,67 +323,67 @@ describe "Acts As Taggable On" do
208
323
  }.should_not raise_error
209
324
  end
210
325
  end
211
-
326
+
212
327
  describe 'Caching' do
213
328
  before(:each) do
214
- @taggable = CachedModel.new(:name => "Bob Jones")
329
+ @taggable = CachedModel.new(:name => "Bob Jones")
215
330
  @another_taggable = OtherCachedModel.new(:name => "John Smith")
216
331
  end
217
-
332
+
218
333
  it "should add saving of tag lists and cached tag lists to the instance" do
219
334
  @taggable.should respond_to(:save_cached_tag_list)
220
335
  @another_taggable.should respond_to(:save_cached_tag_list)
221
-
336
+
222
337
  @taggable.should respond_to(:save_tags)
223
- end
338
+ end
224
339
 
225
340
  it "should add cached tag lists to the instance if cached column is not present" do
226
341
  TaggableModel.new(:name => "Art Kram").should_not respond_to(:save_cached_tag_list)
227
342
  end
228
-
343
+
229
344
  it "should generate a cached column checker for each tag type" do
230
345
  CachedModel.should respond_to(:caching_tag_list?)
231
346
  OtherCachedModel.should respond_to(:caching_language_list?)
232
- end
233
-
347
+ end
348
+
234
349
  it 'should not have cached tags' do
235
- @taggable.cached_tag_list.should be_blank
236
- @another_taggable.cached_language_list.should be_blank
350
+ @taggable.cached_tag_list.should be_blank
351
+ @another_taggable.cached_language_list.should be_blank
237
352
  end
238
-
353
+
239
354
  it 'should cache tags' do
240
355
  @taggable.update_attributes(:tag_list => 'awesome, epic')
241
356
  @taggable.cached_tag_list.should == 'awesome, epic'
242
-
357
+
243
358
  @another_taggable.update_attributes(:language_list => 'ruby, .net')
244
- @another_taggable.cached_language_list.should == 'ruby, .net'
359
+ @another_taggable.cached_language_list.should == 'ruby, .net'
245
360
  end
246
-
361
+
247
362
  it 'should keep the cache' do
248
363
  @taggable.update_attributes(:tag_list => 'awesome, epic')
249
- @taggable = CachedModel.find(@taggable)
364
+ @taggable = CachedModel.find(@taggable)
250
365
  @taggable.save!
251
- @taggable.cached_tag_list.should == 'awesome, epic'
366
+ @taggable.cached_tag_list.should == 'awesome, epic'
252
367
  end
253
-
368
+
254
369
  it 'should update the cache' do
255
370
  @taggable.update_attributes(:tag_list => 'awesome, epic')
256
371
  @taggable.update_attributes(:tag_list => 'awesome')
257
- @taggable.cached_tag_list.should == 'awesome'
372
+ @taggable.cached_tag_list.should == 'awesome'
258
373
  end
259
-
374
+
260
375
  it 'should remove the cache' do
261
376
  @taggable.update_attributes(:tag_list => 'awesome, epic')
262
377
  @taggable.update_attributes(:tag_list => '')
263
- @taggable.cached_tag_list.should be_blank
378
+ @taggable.cached_tag_list.should be_blank
264
379
  end
265
-
380
+
266
381
  it 'should have a tag list' do
267
382
  @taggable.update_attributes(:tag_list => 'awesome, epic')
268
383
  @taggable = CachedModel.find(@taggable.id)
269
384
  @taggable.tag_list.sort.should == %w(awesome epic).sort
270
385
  end
271
-
386
+
272
387
  it 'should keep the tag list' do
273
388
  @taggable.update_attributes(:tag_list => 'awesome, epic')
274
389
  @taggable = CachedModel.find(@taggable.id)
@@ -277,11 +392,63 @@ describe "Acts As Taggable On" do
277
392
  end
278
393
  end
279
394
 
280
- describe "taggings" do
395
+ context 'when tagging context ends in an "s" when singular (ex. "status", "glass", etc.)' do
396
+ describe 'caching' do
397
+ before { @taggable = OtherCachedModel.new(:name => "John Smith") }
398
+ subject { @taggable }
399
+
400
+ it { should respond_to(:save_cached_tag_list) }
401
+ its(:cached_language_list) { should be_blank }
402
+ its(:cached_status_list) { should be_blank }
403
+ its(:cached_glass_list) { should be_blank }
404
+
405
+ context 'language taggings cache after update' do
406
+ before { @taggable.update_attributes(:language_list => 'ruby, .net') }
407
+ subject { @taggable }
408
+
409
+ its(:language_list) { should == ['ruby', '.net']}
410
+ its(:cached_language_list) { should == 'ruby, .net' } # passes
411
+ its(:instance_variables) { should include((RUBY_VERSION < '1.9' ? '@language_list' : :@language_list)) }
412
+ end
413
+
414
+ context 'status taggings cache after update' do
415
+ before { @taggable.update_attributes(:status_list => 'happy, married') }
416
+ subject { @taggable }
417
+
418
+ its(:status_list) { should == ['happy', 'married'] }
419
+ its(:cached_status_list) { should == 'happy, married' } # fails
420
+ its(:cached_status_list) { should_not == '' } # fails, is blank
421
+ its(:instance_variables) { should include((RUBY_VERSION < '1.9' ? '@status_list' : :@status_list)) }
422
+ its(:instance_variables) { should_not include((RUBY_VERSION < '1.9' ? '@statu_list' : :@statu_list)) } # fails, note: one "s"
423
+
424
+ end
425
+
426
+ context 'glass taggings cache after update' do
427
+ before do
428
+ @taggable.update_attributes(:glass_list => 'rectangle, aviator')
429
+ end
430
+
431
+ subject { @taggable }
432
+ its(:glass_list) { should == ['rectangle', 'aviator'] }
433
+ its(:cached_glass_list) { should == 'rectangle, aviator' } # fails
434
+ its(:cached_glass_list) { should_not == '' } # fails, is blank
435
+ if RUBY_VERSION < '1.9'
436
+ its(:instance_variables) { should include('@glass_list') }
437
+ its(:instance_variables) { should_not include('@glas_list') } # fails, note: one "s"
438
+ else
439
+ its(:instance_variables) { should include(:@glass_list) }
440
+ its(:instance_variables) { should_not include(:@glas_list) } # fails, note: one "s"
441
+ end
442
+
443
+ end
444
+ end
445
+ end
446
+
447
+ describe "taggings" do
281
448
  before(:each) do
282
449
  @taggable = TaggableModel.new(:name => "Art Kram")
283
450
  end
284
-
451
+
285
452
  it 'should return [] taggings' do
286
453
  @taggable.taggings.should == []
287
454
  end