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.
- data/.gitignore +1 -0
- data/.travis.yml +1 -2
- data/README.rdoc +27 -50
- data/acts-as-taggable-on.gemspec +4 -3
- data/lib/acts-as-taggable-on.rb +0 -4
- data/lib/acts-as-taggable-on/version.rb +1 -1
- data/lib/acts_as_taggable_on/acts_as_taggable_on.rb +4 -13
- data/lib/acts_as_taggable_on/acts_as_taggable_on/cache.rb +1 -1
- data/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb +1 -1
- data/lib/acts_as_taggable_on/acts_as_taggable_on/core.rb +29 -17
- data/lib/acts_as_taggable_on/acts_as_taggable_on/related.rb +15 -15
- data/lib/acts_as_taggable_on/tag.rb +12 -13
- data/lib/acts_as_taggable_on/tagging.rb +0 -2
- data/lib/acts_as_taggable_on/utils.rb +7 -8
- data/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb +228 -61
- data/spec/acts_as_taggable_on/tag_list_spec.rb +4 -0
- data/spec/acts_as_taggable_on/tag_spec.rb +11 -15
- data/spec/acts_as_taggable_on/taggable_spec.rb +89 -27
- data/spec/acts_as_taggable_on/tagger_spec.rb +14 -0
- data/spec/acts_as_taggable_on/utils_spec.rb +2 -3
- data/spec/database.yml.sample +1 -1
- data/spec/generators/acts_as_taggable_on/migration/migration_generator_spec.rb +22 -0
- data/spec/models.rb +11 -2
- data/spec/schema.rb +7 -0
- data/spec/spec_helper.rb +1 -0
- metadata +95 -122
- 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/compatibility/Gemfile +0 -8
- 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,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
|
-
|
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
|
-
|
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.
|
241
|
+
|
242
|
+
taggable1.offering_list = "one, two"
|
243
|
+
taggable1.need_list = "one, two"
|
173
244
|
taggable1.save
|
174
|
-
|
175
|
-
taggable2.
|
245
|
+
|
246
|
+
taggable2.need_list = "one, two"
|
176
247
|
taggable2.save
|
177
|
-
|
178
|
-
taggable1.
|
179
|
-
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
|
-
|
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
|