acts_as_taggable_on 3.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +9 -0
  5. data/Appraisals +7 -0
  6. data/Gemfile +5 -0
  7. data/Guardfile +5 -0
  8. data/LICENSE.md +20 -0
  9. data/README.md +309 -0
  10. data/Rakefile +13 -0
  11. data/UPGRADING +7 -0
  12. data/acts_as_taggable_on.gemspec +35 -0
  13. data/db/migrate/1_acts_as_taggable_on_migration.rb +30 -0
  14. data/db/migrate/2_add_missing_unique_indices.rb +21 -0
  15. data/gemfiles/rails_3.gemfile +8 -0
  16. data/gemfiles/rails_4.gemfile +8 -0
  17. data/lib/acts_as_taggable_on.rb +61 -0
  18. data/lib/acts_as_taggable_on/acts_as_taggable_on/cache.rb +82 -0
  19. data/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb +187 -0
  20. data/lib/acts_as_taggable_on/acts_as_taggable_on/compatibility.rb +34 -0
  21. data/lib/acts_as_taggable_on/acts_as_taggable_on/core.rb +394 -0
  22. data/lib/acts_as_taggable_on/acts_as_taggable_on/dirty.rb +37 -0
  23. data/lib/acts_as_taggable_on/acts_as_taggable_on/ownership.rb +135 -0
  24. data/lib/acts_as_taggable_on/acts_as_taggable_on/related.rb +84 -0
  25. data/lib/acts_as_taggable_on/engine.rb +6 -0
  26. data/lib/acts_as_taggable_on/tag.rb +119 -0
  27. data/lib/acts_as_taggable_on/tag_list.rb +101 -0
  28. data/lib/acts_as_taggable_on/taggable.rb +105 -0
  29. data/lib/acts_as_taggable_on/tagger.rb +76 -0
  30. data/lib/acts_as_taggable_on/tagging.rb +34 -0
  31. data/lib/acts_as_taggable_on/tags_helper.rb +15 -0
  32. data/lib/acts_as_taggable_on/utils.rb +34 -0
  33. data/lib/acts_as_taggable_on/version.rb +4 -0
  34. data/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb +265 -0
  35. data/spec/acts_as_taggable_on/acts_as_tagger_spec.rb +114 -0
  36. data/spec/acts_as_taggable_on/caching_spec.rb +77 -0
  37. data/spec/acts_as_taggable_on/related_spec.rb +143 -0
  38. data/spec/acts_as_taggable_on/single_table_inheritance_spec.rb +187 -0
  39. data/spec/acts_as_taggable_on/tag_list_spec.rb +126 -0
  40. data/spec/acts_as_taggable_on/tag_spec.rb +211 -0
  41. data/spec/acts_as_taggable_on/taggable_spec.rb +623 -0
  42. data/spec/acts_as_taggable_on/tagger_spec.rb +137 -0
  43. data/spec/acts_as_taggable_on/tagging_spec.rb +28 -0
  44. data/spec/acts_as_taggable_on/tags_helper_spec.rb +44 -0
  45. data/spec/acts_as_taggable_on/utils_spec.rb +21 -0
  46. data/spec/bm.rb +52 -0
  47. data/spec/database.yml.sample +19 -0
  48. data/spec/models.rb +58 -0
  49. data/spec/schema.rb +65 -0
  50. data/spec/spec_helper.rb +87 -0
  51. metadata +248 -0
@@ -0,0 +1,114 @@
1
+ require 'spec_helper'
2
+
3
+ describe "acts_as_tagger" do
4
+ before(:each) do
5
+ clean_database!
6
+ end
7
+
8
+ describe "Tagger Method Generation" do
9
+ before(:each) do
10
+ @tagger = User.new
11
+ end
12
+
13
+ it "should add #is_tagger? query method to the class-side" do
14
+ User.should respond_to(:is_tagger?)
15
+ end
16
+
17
+ it "should return true from the class-side #is_tagger?" do
18
+ User.is_tagger?.should be_true
19
+ end
20
+
21
+ it "should return false from the base #is_tagger?" do
22
+ ActiveRecord::Base.is_tagger?.should be_false
23
+ end
24
+
25
+ it "should add #is_tagger? query method to the singleton" do
26
+ @tagger.should respond_to(:is_tagger?)
27
+ end
28
+
29
+ it "should add #tag method on the instance-side" do
30
+ @tagger.should respond_to(:tag)
31
+ end
32
+
33
+ it "should generate an association for #owned_taggings and #owned_tags" do
34
+ @tagger.should respond_to(:owned_taggings, :owned_tags)
35
+ end
36
+ end
37
+
38
+ describe "#tag" do
39
+ context 'when called with a non-existent tag context' do
40
+ before(:each) do
41
+ @tagger = User.new
42
+ @taggable = TaggableModel.new(:name=>"Richard Prior")
43
+ end
44
+
45
+ it "should by default not throw an exception " do
46
+ @taggable.tag_list_on(:foo).should be_empty
47
+ lambda {
48
+ @tagger.tag(@taggable, :with=>'this, and, that', :on=>:foo)
49
+ }.should_not raise_error
50
+ end
51
+
52
+ it 'should by default create the tag context on-the-fly' do
53
+ @taggable.tag_list_on(:here_ond_now).should be_empty
54
+ @tagger.tag(@taggable, :with=>'that', :on => :here_ond_now)
55
+ @taggable.tag_list_on(:here_ond_now).should_not include('that')
56
+ @taggable.all_tags_list_on(:here_ond_now).should include('that')
57
+ end
58
+
59
+ it "should show all the tag list when both public and owned tags exist" do
60
+ @taggable.tag_list = 'ruby, python'
61
+ @tagger.tag(@taggable, :with => 'java, lisp', :on => :tags)
62
+ @taggable.all_tags_on(:tags).map(&:name).sort.should == %w(ruby python java lisp).sort
63
+ end
64
+
65
+ it "should not add owned tags to the common list" do
66
+ @taggable.tag_list = 'ruby, python'
67
+ @tagger.tag(@taggable, :with => 'java, lisp', :on => :tags)
68
+ @taggable.tag_list.should == %w(ruby python)
69
+ @tagger.tag(@taggable, :with => '', :on => :tags)
70
+ @taggable.tag_list.should == %w(ruby python)
71
+ end
72
+
73
+ it "should throw an exception when the default is over-ridden" do
74
+ @taggable.tag_list_on(:foo_boo).should be_empty
75
+ lambda {
76
+ @tagger.tag(@taggable, :with=>'this, and, that', :on=>:foo_boo, :force=>false)
77
+ }.should raise_error
78
+ end
79
+
80
+ it "should not create the tag context on-the-fly when the default is over-ridden" do
81
+ @taggable.tag_list_on(:foo_boo).should be_empty
82
+ @tagger.tag(@taggable, :with=>'this, and, that', :on=>:foo_boo, :force=>false) rescue
83
+ @taggable.tag_list_on(:foo_boo).should be_empty
84
+ end
85
+ end
86
+
87
+ describe "when called by multiple tagger's" do
88
+ before(:each) do
89
+ @user_x = User.create(:name => "User X")
90
+ @user_y = User.create(:name => "User Y")
91
+ @taggable = TaggableModel.create(:name => 'acts_as_taggable_on', :tag_list => 'plugin')
92
+
93
+ @user_x.tag(@taggable, :with => 'ruby, rails', :on => :tags)
94
+ @user_y.tag(@taggable, :with => 'ruby, plugin', :on => :tags)
95
+
96
+ @user_y.tag(@taggable, :with => '', :on => :tags)
97
+ @user_y.tag(@taggable, :with => '', :on => :tags)
98
+ end
99
+
100
+ it "should delete owned tags" do
101
+ @user_y.owned_tags.should == []
102
+ end
103
+
104
+ it "should not delete other taggers tags" do
105
+ @user_x.owned_tags.should have(2).items
106
+ end
107
+
108
+ it "should not delete original tags" do
109
+ @taggable.all_tags_list_on(:tags).should include('plugin')
110
+ end
111
+ end
112
+ end
113
+
114
+ end
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Acts As Taggable On" do
4
+
5
+ before(:each) do
6
+ clean_database!
7
+ end
8
+
9
+ describe 'Caching' do
10
+ before(:each) do
11
+ @taggable = CachedModel.new(:name => "Bob Jones")
12
+ @another_taggable = OtherCachedModel.new(:name => "John Smith")
13
+ end
14
+
15
+ it "should add saving of tag lists and cached tag lists to the instance" do
16
+ @taggable.should respond_to(:save_cached_tag_list)
17
+ @another_taggable.should respond_to(:save_cached_tag_list)
18
+
19
+ @taggable.should respond_to(:save_tags)
20
+ end
21
+
22
+ it "should add cached tag lists to the instance if cached column is not present" do
23
+ TaggableModel.new(:name => "Art Kram").should_not respond_to(:save_cached_tag_list)
24
+ end
25
+
26
+ it "should generate a cached column checker for each tag type" do
27
+ CachedModel.should respond_to(:caching_tag_list?)
28
+ OtherCachedModel.should respond_to(:caching_language_list?)
29
+ end
30
+
31
+ it 'should not have cached tags' do
32
+ @taggable.cached_tag_list.should be_blank
33
+ @another_taggable.cached_language_list.should be_blank
34
+ end
35
+
36
+ it 'should cache tags' do
37
+ @taggable.update_attributes(:tag_list => 'awesome, epic')
38
+ @taggable.cached_tag_list.should == 'awesome, epic'
39
+
40
+ @another_taggable.update_attributes(:language_list => 'ruby, .net')
41
+ @another_taggable.cached_language_list.should == 'ruby, .net'
42
+ end
43
+
44
+ it 'should keep the cache' do
45
+ @taggable.update_attributes(:tag_list => 'awesome, epic')
46
+ @taggable = CachedModel.find(@taggable)
47
+ @taggable.save!
48
+ @taggable.cached_tag_list.should == 'awesome, epic'
49
+ end
50
+
51
+ it 'should update the cache' do
52
+ @taggable.update_attributes(:tag_list => 'awesome, epic')
53
+ @taggable.update_attributes(:tag_list => 'awesome')
54
+ @taggable.cached_tag_list.should == 'awesome'
55
+ end
56
+
57
+ it 'should remove the cache' do
58
+ @taggable.update_attributes(:tag_list => 'awesome, epic')
59
+ @taggable.update_attributes(:tag_list => '')
60
+ @taggable.cached_tag_list.should be_blank
61
+ end
62
+
63
+ it 'should have a tag list' do
64
+ @taggable.update_attributes(:tag_list => 'awesome, epic')
65
+ @taggable = CachedModel.find(@taggable.id)
66
+ @taggable.tag_list.sort.should == %w(awesome epic).sort
67
+ end
68
+
69
+ it 'should keep the tag list' do
70
+ @taggable.update_attributes(:tag_list => 'awesome, epic')
71
+ @taggable = CachedModel.find(@taggable.id)
72
+ @taggable.save!
73
+ @taggable.tag_list.sort.should == %w(awesome epic).sort
74
+ end
75
+ end
76
+
77
+ end
@@ -0,0 +1,143 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Acts As Taggable On" do
4
+ before(:each) do
5
+ clean_database!
6
+ end
7
+
8
+ describe "Related Objects" do
9
+ it "should find related objects based on tag names on context" do
10
+ taggable1 = TaggableModel.create!(:name => "Taggable 1")
11
+ taggable2 = TaggableModel.create!(:name => "Taggable 2")
12
+ taggable3 = TaggableModel.create!(:name => "Taggable 3")
13
+
14
+ taggable1.tag_list = "one, two"
15
+ taggable1.save
16
+
17
+ taggable2.tag_list = "three, four"
18
+ taggable2.save
19
+
20
+ taggable3.tag_list = "one, four"
21
+ taggable3.save
22
+
23
+ taggable1.find_related_tags.should include(taggable3)
24
+ taggable1.find_related_tags.should_not include(taggable2)
25
+ end
26
+
27
+ it "finds related tags for ordered taggable on" do
28
+ taggable1 = OrderedTaggableModel.create!(:name => "Taggable 1")
29
+ taggable2 = OrderedTaggableModel.create!(:name => "Taggable 2")
30
+ taggable3 = OrderedTaggableModel.create!(:name => "Taggable 3")
31
+
32
+ taggable1.colour_list = "one, two"
33
+ taggable1.save
34
+
35
+ taggable2.colour_list = "three, four"
36
+ taggable2.save
37
+
38
+ taggable3.colour_list = "one, four"
39
+ taggable3.save
40
+
41
+ taggable1.find_related_colours.should include(taggable3)
42
+ taggable1.find_related_colours.should_not include(taggable2)
43
+ end
44
+
45
+ it "should find related objects based on tag names on context - non standard id" do
46
+ taggable1 = NonStandardIdTaggableModel.create!(:name => "Taggable 1")
47
+ taggable2 = NonStandardIdTaggableModel.create!(:name => "Taggable 2")
48
+ taggable3 = NonStandardIdTaggableModel.create!(:name => "Taggable 3")
49
+
50
+ taggable1.tag_list = "one, two"
51
+ taggable1.save
52
+
53
+ taggable2.tag_list = "three, four"
54
+ taggable2.save
55
+
56
+ taggable3.tag_list = "one, four"
57
+ taggable3.save
58
+
59
+ taggable1.find_related_tags.should include(taggable3)
60
+ taggable1.find_related_tags.should_not include(taggable2)
61
+ end
62
+
63
+ it "should find other related objects based on tag names on context" do
64
+ taggable1 = TaggableModel.create!(:name => "Taggable 1")
65
+ taggable2 = OtherTaggableModel.create!(:name => "Taggable 2")
66
+ taggable3 = OtherTaggableModel.create!(:name => "Taggable 3")
67
+
68
+ taggable1.tag_list = "one, two"
69
+ taggable1.save
70
+
71
+ taggable2.tag_list = "three, four"
72
+ taggable2.save
73
+
74
+ taggable3.tag_list = "one, four"
75
+ taggable3.save
76
+
77
+ taggable1.find_related_tags_for(OtherTaggableModel).should include(taggable3)
78
+ taggable1.find_related_tags_for(OtherTaggableModel).should_not include(taggable2)
79
+ end
80
+
81
+ it "should not include the object itself in the list of related objects" do
82
+ taggable1 = TaggableModel.create!(:name => "Taggable 1")
83
+ taggable2 = TaggableModel.create!(:name => "Taggable 2")
84
+
85
+ taggable1.tag_list = "one"
86
+ taggable1.save
87
+
88
+ taggable2.tag_list = "one, two"
89
+ taggable2.save
90
+
91
+ taggable1.find_related_tags.should include(taggable2)
92
+ taggable1.find_related_tags.should_not include(taggable1)
93
+ end
94
+
95
+ it "should not include the object itself in the list of related objects - non standard id" do
96
+ taggable1 = NonStandardIdTaggableModel.create!(:name => "Taggable 1")
97
+ taggable2 = NonStandardIdTaggableModel.create!(:name => "Taggable 2")
98
+
99
+ taggable1.tag_list = "one"
100
+ taggable1.save
101
+
102
+ taggable2.tag_list = "one, two"
103
+ taggable2.save
104
+
105
+ taggable1.find_related_tags.should include(taggable2)
106
+ taggable1.find_related_tags.should_not include(taggable1)
107
+ end
108
+
109
+ context "Ignored Tags" do
110
+ let(:taggable1) { TaggableModel.create!(:name => "Taggable 1") }
111
+ let(:taggable2) { TaggableModel.create!(:name => "Taggable 2") }
112
+ let(:taggable3) { TaggableModel.create!(:name => "Taggable 3") }
113
+ before(:each) do
114
+ taggable1.tag_list = "one, two, four"
115
+ taggable1.save
116
+
117
+ taggable2.tag_list = "two, three"
118
+ taggable2.save
119
+
120
+ taggable3.tag_list = "one, three"
121
+ taggable3.save
122
+ end
123
+ it "should not include ignored tags in related search" do
124
+ taggable1.find_related_tags(:ignore => 'two').should_not include(taggable2)
125
+ taggable1.find_related_tags(:ignore => 'two').should include(taggable3)
126
+ end
127
+
128
+ it "should accept array of ignored tags" do
129
+ taggable4 = TaggableModel.create!(:name => "Taggable 4")
130
+ taggable4.tag_list = "four"
131
+ taggable4.save
132
+
133
+ taggable1.find_related_tags(:ignore => ['two', 'four']).should_not include(taggable2)
134
+ taggable1.find_related_tags(:ignore => ['two', 'four']).should_not include(taggable4)
135
+ end
136
+
137
+ it "should accept symbols as ignored tags" do
138
+ taggable1.find_related_tags(:ignore => :two).should_not include(taggable2)
139
+ end
140
+ end
141
+
142
+ end
143
+ end
@@ -0,0 +1,187 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Single Table Inheritance" do
4
+
5
+ before(:each) do
6
+ clean_database!
7
+ end
8
+
9
+ let(:taggable) { TaggableModel.new(:name => "taggable model") }
10
+
11
+ let(:inheriting_model) { InheritingTaggableModel.new(:name => "Inheriting Taggable Model") }
12
+ let(:altered_inheriting) { AlteredInheritingTaggableModel.new(:name => "Altered Inheriting Model") }
13
+
14
+ 1.upto(4) do |n|
15
+ let(:"inheriting_#{n}") { InheritingTaggableModel.new(:name => "Inheriting Model #{n}") }
16
+ end
17
+
18
+ let(:student) { Student.create! }
19
+
20
+ describe "tag contexts" do
21
+ it "should pass on to STI-inherited models" do
22
+ inheriting_model.should respond_to(:tag_list, :skill_list, :language_list)
23
+ altered_inheriting.should respond_to(:tag_list, :skill_list, :language_list)
24
+ end
25
+
26
+ it "should pass on to altered STI models" do
27
+ altered_inheriting.should respond_to(:part_list)
28
+ end
29
+ end
30
+
31
+ context "matching contexts" do
32
+
33
+ before do
34
+ inheriting_1.offering_list = "one, two"
35
+ inheriting_1.need_list = "one, two"
36
+ inheriting_1.save!
37
+
38
+ inheriting_2.need_list = "one, two"
39
+ inheriting_2.save!
40
+
41
+ inheriting_3.offering_list = "one, two"
42
+ inheriting_3.save!
43
+
44
+ inheriting_4.tag_list = "one, two, three, four"
45
+ inheriting_4.save!
46
+
47
+ taggable.need_list = "one, two"
48
+ taggable.save!
49
+ end
50
+
51
+ it "should find objects with tags of matching contexts" do
52
+ inheriting_1.find_matching_contexts(:offerings, :needs).should include(inheriting_2)
53
+ inheriting_1.find_matching_contexts(:offerings, :needs).should_not include(inheriting_3)
54
+ inheriting_1.find_matching_contexts(:offerings, :needs).should_not include(inheriting_4)
55
+ inheriting_1.find_matching_contexts(:offerings, :needs).should_not include(taggable)
56
+
57
+ inheriting_1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should include(inheriting_2)
58
+ inheriting_1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should_not include(inheriting_3)
59
+ inheriting_1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should_not include(inheriting_4)
60
+ inheriting_1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should include(taggable)
61
+ end
62
+
63
+ it "should not include the object itself in the list of related objects with tags of matching contexts" do
64
+ inheriting_1.find_matching_contexts(:offerings, :needs).should_not include(inheriting_1)
65
+ inheriting_1.find_matching_contexts_for(InheritingTaggableModel, :offerings, :needs).should_not include(inheriting_1)
66
+ inheriting_1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should_not include(inheriting_1)
67
+ end
68
+ end
69
+
70
+ context "find related tags" do
71
+ before do
72
+ inheriting_1.tag_list = "one, two"
73
+ inheriting_1.save
74
+
75
+ inheriting_2.tag_list = "three, four"
76
+ inheriting_2.save
77
+
78
+ inheriting_3.tag_list = "one, four"
79
+ inheriting_3.save
80
+
81
+ taggable.tag_list = "one, two, three, four"
82
+ taggable.save
83
+ end
84
+
85
+ it "should find related objects based on tag names on context" do
86
+ inheriting_1.find_related_tags.should include(inheriting_3)
87
+ inheriting_1.find_related_tags.should_not include(inheriting_2)
88
+ inheriting_1.find_related_tags.should_not include(taggable)
89
+
90
+ inheriting_1.find_related_tags_for(TaggableModel).should include(inheriting_3)
91
+ inheriting_1.find_related_tags_for(TaggableModel).should_not include(inheriting_2)
92
+ inheriting_1.find_related_tags_for(TaggableModel).should include(taggable)
93
+ end
94
+
95
+ it "should not include the object itself in the list of related objects" do
96
+ inheriting_1.find_related_tags.should_not include(inheriting_1)
97
+ inheriting_1.find_related_tags_for(InheritingTaggableModel).should_not include(inheriting_1)
98
+ inheriting_1.find_related_tags_for(TaggableModel).should_not include(inheriting_1)
99
+ end
100
+ end
101
+
102
+ describe "tag list" do
103
+ before do
104
+ @inherited_same = InheritingTaggableModel.new(:name => "inherited same")
105
+ @inherited_different = AlteredInheritingTaggableModel.new(:name => "inherited different")
106
+ end
107
+
108
+ it "should be able to save tags for inherited models" do
109
+ inheriting_model.tag_list = "bob, kelso"
110
+ inheriting_model.save
111
+ InheritingTaggableModel.tagged_with("bob").first.should == inheriting_model
112
+ end
113
+
114
+ it "should find STI tagged models on the superclass" do
115
+ inheriting_model.tag_list = "bob, kelso"
116
+ inheriting_model.save
117
+ TaggableModel.tagged_with("bob").first.should == inheriting_model
118
+ end
119
+
120
+ it "should be able to add on contexts only to some subclasses" do
121
+ altered_inheriting.part_list = "fork, spoon"
122
+ altered_inheriting.save
123
+ InheritingTaggableModel.tagged_with("fork", :on => :parts).should be_empty
124
+ AlteredInheritingTaggableModel.tagged_with("fork", :on => :parts).first.should == altered_inheriting
125
+ end
126
+
127
+ it "should have different tag_counts_on for inherited models" do
128
+ inheriting_model.tag_list = "bob, kelso"
129
+ inheriting_model.save!
130
+ altered_inheriting.tag_list = "fork, spoon"
131
+ altered_inheriting.save!
132
+
133
+ InheritingTaggableModel.tag_counts_on(:tags, :order => 'tags.id').map(&:name).should == %w(bob kelso)
134
+ AlteredInheritingTaggableModel.tag_counts_on(:tags, :order => 'tags.id').map(&:name).should == %w(fork spoon)
135
+ TaggableModel.tag_counts_on(:tags, :order => 'tags.id').map(&:name).should == %w(bob kelso fork spoon)
136
+ end
137
+
138
+ it "should have different tags_on for inherited models" do
139
+ inheriting_model.tag_list = "bob, kelso"
140
+ inheriting_model.save!
141
+ altered_inheriting.tag_list = "fork, spoon"
142
+ altered_inheriting.save!
143
+
144
+ InheritingTaggableModel.tags_on(:tags, :order => 'tags.id').map(&:name).should == %w(bob kelso)
145
+ AlteredInheritingTaggableModel.tags_on(:tags, :order => 'tags.id').map(&:name).should == %w(fork spoon)
146
+ TaggableModel.tags_on(:tags, :order => 'tags.id').map(&:name).should == %w(bob kelso fork spoon)
147
+ end
148
+
149
+ it 'should store same tag without validation conflict' do
150
+ taggable.tag_list = 'one'
151
+ taggable.save!
152
+
153
+ inheriting_model.tag_list = 'one'
154
+ inheriting_model.save!
155
+
156
+ inheriting_model.update_attributes! :name => 'foo'
157
+ end
158
+ end
159
+
160
+ describe "ownership" do
161
+ it "should have taggings" do
162
+ student.tag(taggable, :with=>'ruby,scheme', :on=>:tags)
163
+ student.owned_taggings.should have(2).tags
164
+ end
165
+
166
+ it "should have tags" do
167
+ student.tag(taggable, :with=>'ruby,scheme', :on=>:tags)
168
+ student.owned_tags.should have(2).tags
169
+ end
170
+
171
+ it "should return tags for the inheriting tagger" do
172
+ student.tag(taggable, :with => 'ruby, scheme', :on => :tags)
173
+ taggable.tags_from(student).should match_array(%w(ruby scheme))
174
+ end
175
+
176
+ it "returns owner tags on the tagger" do
177
+ student.tag(taggable, :with => 'ruby, scheme', :on => :tags)
178
+ taggable.owner_tags_on(student, :tags).should have(2).tags
179
+ end
180
+
181
+ it "should scope objects returned by tagged_with by owners" do
182
+ student.tag(taggable, :with => 'ruby, scheme', :on => :tags)
183
+ TaggableModel.tagged_with(%w(ruby scheme), :owned_by => student).should have(1).tag
184
+ end
185
+ end
186
+
187
+ end