acts-as-taggable-on 2.0.0.pre3 → 2.0.0.pre4

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.0.0.pre3
1
+ 2.0.0.pre4
@@ -31,11 +31,11 @@ module ActsAsTaggableOn
31
31
  end
32
32
  end
33
33
 
34
- include Core
35
- include Aggregate
36
- include Cache
37
- include Ownership
38
- include Related
34
+ include ActsAsTaggableOn::Taggable::Core
35
+ include ActsAsTaggableOn::Taggable::Aggregate
36
+ include ActsAsTaggableOn::Taggable::Cache
37
+ include ActsAsTaggableOn::Taggable::Ownership
38
+ include ActsAsTaggableOn::Taggable::Related
39
39
  end
40
40
  end
41
41
  end
@@ -1,8 +1,10 @@
1
1
  module ActsAsTaggableOn::Taggable
2
2
  module Aggregate
3
3
  def self.included(base)
4
- include InstanceMethods
5
- base.extend ClassMethods
4
+ unless base.ancestors.include?(ActsAsTaggableOn::Taggable::Aggregate::InstanceMethods)
5
+ base.send :include, ActsAsTaggableOn::Taggable::Aggregate::InstanceMethods
6
+ base.extend ActsAsTaggableOn::Taggable::Aggregate::ClassMethods
7
+ end
6
8
 
7
9
  base.tag_types.map(&:to_s).each do |tag_type|
8
10
  base.class_eval %(
@@ -3,6 +3,9 @@ module ActsAsTaggableOn::Taggable
3
3
  def self.included(base)
4
4
  # Skip adding caching capabilities if no cache columns exist
5
5
  return unless base.tag_types.any? { |context| base.column_names.include?("cached_#{context.to_s.singularize}_list") }
6
+
7
+ base.send :include, ActsAsTaggableOn::Taggable::Cache::InstanceMethods
8
+ base.extend ActsAsTaggableOn::Taggable::Cache::ClassMethods
6
9
 
7
10
  base.class_eval do
8
11
  before_save :save_cached_tag_list
@@ -15,9 +18,6 @@ module ActsAsTaggableOn::Taggable
15
18
  end
16
19
  )
17
20
  end
18
-
19
- base.extend ClassMethods
20
- include InstanceMethods
21
21
  end
22
22
 
23
23
  module ClassMethods
@@ -1,6 +1,9 @@
1
1
  module ActsAsTaggableOn::Taggable
2
2
  module Core
3
3
  def self.included(base)
4
+ base.send :include, ActsAsTaggableOn::Taggable::Core::InstanceMethods
5
+ base.extend ActsAsTaggableOn::Taggable::Core::ClassMethods
6
+
4
7
  base.class_eval do
5
8
  attr_writer :custom_contexts
6
9
 
@@ -39,9 +42,6 @@ module ActsAsTaggableOn::Taggable
39
42
  end
40
43
  )
41
44
  end
42
-
43
- base.extend ClassMethods
44
- include InstanceMethods
45
45
  end
46
46
 
47
47
  module ClassMethods
@@ -142,6 +142,7 @@ module ActsAsTaggableOn::Taggable
142
142
  def all_tags_list_on(context)
143
143
  variable_name = "@all_#{context.to_s.singularize}_list"
144
144
  return instance_variable_get(variable_name) if instance_variable_get(variable_name)
145
+
145
146
  instance_variable_set(variable_name, TagList.new(all_tags_on(context).map(&:name)).freeze)
146
147
  end
147
148
 
@@ -149,7 +150,7 @@ module ActsAsTaggableOn::Taggable
149
150
  # Returns all tags of a given context
150
151
  def all_tags_on(context)
151
152
  opts = ["#{Tagging.table_name}.context = ?", context.to_s]
152
- base_tags.where(opts).order("#{Tagging.table_name}.created_at")
153
+ base_tags.where(opts).order("#{Tagging.table_name}.created_at").group("#{Tagging.table_name}.tag_id").all
153
154
  end
154
155
 
155
156
  ##
@@ -169,6 +170,15 @@ module ActsAsTaggableOn::Taggable
169
170
  custom_contexts + self.class.tag_types.map(&:to_s)
170
171
  end
171
172
 
173
+ def reload
174
+ self.class.tag_types.each do |context|
175
+ instance_variable_set("@#{context.to_s.singularize}_list", nil)
176
+ instance_variable_set("@all_#{context.to_s.singularize}_list", nil)
177
+ end
178
+
179
+ super
180
+ end
181
+
172
182
  def save_tags
173
183
  transaction do
174
184
  tagging_contexts.each do |context|
@@ -184,13 +194,13 @@ module ActsAsTaggableOn::Taggable
184
194
  # Find taggings to remove:
185
195
  old_taggings = Tagging.where(:taggable_id => self.id, :taggable_type => self.class.base_class.to_s,
186
196
  :tagger_type => nil, :tagger_id => nil,
187
- :context => context, :tag_id => old_tags)
197
+ :context => context.to_s, :tag_id => old_tags)
188
198
 
189
199
  Tagging.destroy_all :id => old_taggings.map(&:id)
190
200
 
191
201
  # Create new taggings:
192
202
  new_tags.each do |tag|
193
- Tagging.create!(:tag_id => tag.id, :context => context, :taggable => self)
203
+ Tagging.create!(:tag_id => tag.id, :context => context.to_s, :taggable => self)
194
204
  end
195
205
  end
196
206
  end
@@ -1,8 +1,12 @@
1
1
  module ActsAsTaggableOn::Taggable
2
2
  module Ownership
3
3
  def self.included(base)
4
- include InstanceMethods
5
- base.extend ClassMethods
4
+ base.send :include, ActsAsTaggableOn::Taggable::Ownership::InstanceMethods
5
+ base.extend ActsAsTaggableOn::Taggable::Ownership::ClassMethods
6
+
7
+ base.class_eval do
8
+ after_save :save_owned_tags
9
+ end
6
10
 
7
11
  base.tag_types.map(&:to_s).each do |tag_type|
8
12
  base.class_eval %(
@@ -17,34 +21,50 @@ module ActsAsTaggableOn::Taggable
17
21
  end
18
22
 
19
23
  module InstanceMethods
24
+ def owner_tags_on(owner, context)
25
+ base_tags.where([%(#{Tagging.table_name}.context = ? AND
26
+ #{Tagging.table_name}.tagger_id = ? AND
27
+ #{Tagging.table_name}.tagger_type = ?), context.to_s, owner.id, owner.class.to_s]).all
28
+ end
29
+
20
30
  def cached_owned_tag_list_on(context)
21
31
  variable_name = "@owned_#{context}_list"
22
32
  cache = instance_variable_get(variable_name) || instance_variable_set(variable_name, {})
23
33
  end
24
34
 
25
35
  def owner_tag_list_on(owner, context)
36
+ add_custom_context(context)
37
+
26
38
  cache = cached_owned_tag_list_on(context)
39
+ cache.delete_if { |key, value| key.id == owner.id && key.class == owner.class }
40
+
27
41
  cache[owner] ||= TagList.new(*owner_tags_on(owner, context).map(&:name))
28
42
  end
29
-
30
- def owner_tags_on(owner, context)
31
- base_tags.where([%(#{Tagging.table_name}.context = ? AND
32
- #{Tagging.table_name}.tagger_id = ? AND
33
- #{Tagging.table_name}.tagger_type = ?), context.to_s, owner.id, owner.class.to_s])
34
- end
35
43
 
36
44
  def set_owner_tag_list_on(owner, context, new_list)
45
+ add_custom_context(context)
46
+
37
47
  cache = cached_owned_tag_list_on(context)
48
+ cache.delete_if { |key, value| key.id == owner.id && key.class == owner.class }
49
+
38
50
  cache[owner] = TagList.from(new_list)
39
51
  end
52
+
53
+ def reload
54
+ self.class.tag_types.each do |context|
55
+ instance_variable_set("@owned_#{context}_list", nil)
56
+ end
57
+
58
+ super
59
+ end
40
60
 
41
- def save_tags
61
+ def save_owned_tags
42
62
  transaction do
43
63
  tagging_contexts.each do |context|
44
64
  cached_owned_tag_list_on(context).each do |owner, tag_list|
45
65
  # Find existing tags or create non-existing tags:
46
66
  tag_list = Tag.find_or_create_all_with_like_by_name(tag_list.uniq)
47
-
67
+
48
68
  owned_tags = owner_tags_on(owner, context)
49
69
 
50
70
  old_tags = owned_tags - tag_list
@@ -56,17 +76,17 @@ module ActsAsTaggableOn::Taggable
56
76
  :tagger_type => owner.class.to_s, :tagger_id => owner.id,
57
77
  :tag_id => old_tags, :context => context)
58
78
 
59
- # Destroy old taggings:
60
- Tagging.destroy_all(:id => old_taggings.map(&:id))
79
+ if old_taggings.present?
80
+ # Destroy old taggings:
81
+ Tagging.destroy_all(:id => old_taggings.map(&:id))
82
+ end
61
83
 
62
84
  # Create new taggings:
63
85
  new_tags.each do |tag|
64
- Tagging.create!(:tag_id => tag.id, :context => context, :tagger => owner, :taggable => self)
86
+ Tagging.create!(:tag_id => tag.id, :context => context.to_s, :tagger => owner, :taggable => self)
65
87
  end
66
88
  end
67
89
  end
68
-
69
- super
70
90
  end
71
91
  end
72
92
  end
@@ -1,8 +1,10 @@
1
1
  module ActsAsTaggableOn::Taggable
2
2
  module Related
3
3
  def self.included(base)
4
- include InstanceMethods
5
- base.extend ClassMethods
4
+ unless base.ancestors.include?(ActsAsTaggableOn::Taggable::Related::InstanceMethods)
5
+ base.send :include, ActsAsTaggableOn::Taggable::Related::InstanceMethods
6
+ base.extend ActsAsTaggableOn::Taggable::Related::ClassMethods
7
+ end
6
8
 
7
9
  base.tag_types.map(&:to_s).each do |tag_type|
8
10
  base.class_eval %(
@@ -20,9 +20,6 @@ module ActsAsTaggableOn
20
20
  end
21
21
 
22
22
  module InstanceMethods
23
- def self.included(base)
24
- end
25
-
26
23
  def tag(taggable, opts={})
27
24
  opts.reverse_merge!(:force => true)
28
25
 
@@ -0,0 +1 @@
1
+ require 'acts-as-taggable-on'
@@ -64,8 +64,9 @@ describe "acts_as_tagger" do
64
64
 
65
65
  it "should not add owned tags to the common list" do
66
66
  @taggable.tag_list = 'ruby, python'
67
- @tagger.tag(@taggable, :with => 'java, lisp', :on => :foo)
68
- @tagger.tag(@taggable, :with => '', :on => :foo)
67
+ @tagger.tag(@taggable, :with => 'java, lisp', :on => :tags)
68
+ @taggable.tag_list.should == %w(ruby python)
69
+ @tagger.tag(@taggable, :with => '', :on => :tags)
69
70
  @taggable.tag_list.should == %w(ruby python)
70
71
  end
71
72
 
@@ -3,8 +3,8 @@ require File.dirname(__FILE__) + '/../spec_helper'
3
3
  describe "Tagger" do
4
4
  before(:each) do
5
5
  clean_database!
6
- @user = TaggableUser.new
7
- @taggable = TaggableModel.new(:name => "Bob Jones")
6
+ @user = TaggableUser.create
7
+ @taggable = TaggableModel.create(:name => "Bob Jones")
8
8
  end
9
9
 
10
10
  it "should have taggings" do
@@ -17,13 +17,15 @@ describe "Tagger" do
17
17
  @user.owned_tags.size == 2
18
18
  end
19
19
 
20
- it "should not overlap or lose tags from different users" do
20
+ it "should not overlap tags from different taggers" do
21
21
  @user2 = TaggableUser.new
22
22
  lambda{
23
23
  @user.tag(@taggable, :with => 'ruby, scheme', :on => :tags)
24
24
  @user2.tag(@taggable, :with => 'java, python, lisp, ruby', :on => :tags)
25
25
  }.should change(Tagging, :count).by(6)
26
26
 
27
+ [@user, @user2, @taggable].each(&:reload)
28
+
27
29
  @user.owned_tags.map(&:name).sort.should == %w(ruby scheme).sort
28
30
  @user2.owned_tags.map(&:name).sort.should == %w(java python lisp ruby).sort
29
31
 
@@ -31,23 +33,40 @@ describe "Tagger" do
31
33
  @taggable.tags_from(@user2).sort.should == %w(java lisp python ruby).sort
32
34
 
33
35
  @taggable.all_tags_list.sort.should == %w(ruby scheme java python lisp).sort
34
- @taggable.all_tags_on(:tags).size.should == 6
36
+ @taggable.all_tags_on(:tags).size.should == 5
35
37
  end
38
+
39
+ it "should not lose tags from different taggers" do
40
+ @user2 = TaggableUser.create
41
+ @user2.tag(@taggable, :with => 'java, python, lisp, ruby', :on => :tags)
42
+ @user.tag(@taggable, :with => 'ruby, scheme', :on => :tags)
43
+
44
+ lambda {
45
+ @user2.tag(@taggable, :with => 'java, python, lisp', :on => :tags)
46
+ }.should change(Tagging, :count).by(-1)
36
47
 
37
- it "should not lose tags" do
38
- @taggable.update_attributes(:tag_list => 'ruby')
39
- @user.tag(@taggable, :with => 'ruby, scheme', :on => :tags)
48
+ [@user, @user2, @taggable].each(&:reload)
40
49
 
41
- [@taggable, @user].each(&:reload)
42
- @taggable.tag_list.should == %w(ruby)
43
- @taggable.all_tags_list.sort.should == %w(ruby scheme).sort
50
+ @taggable.tags_from(@user).sort.should == %w(ruby scheme).sort
51
+ @taggable.tags_from(@user2).sort.should == %w(java python lisp).sort
44
52
 
53
+ @taggable.all_tags_list.sort.should == %w(ruby scheme java python lisp).sort
54
+ @taggable.all_tags_on(:tags).length.should == 5
55
+ end
56
+
57
+ it "should not lose tags" do
58
+ @user2 = TaggableUser.create
59
+
60
+ @user.tag(@taggable, :with => 'awesome', :on => :tags)
61
+ @user2.tag(@taggable, :with => 'awesome, epic', :on => :tags)
62
+
45
63
  lambda {
46
- @taggable.update_attributes(:tag_list => "")
64
+ @user2.tag(@taggable, :with => 'epic', :on => :tags)
47
65
  }.should change(Tagging, :count).by(-1)
48
-
49
- @taggable.tag_list.should == []
50
- @taggable.all_tags_list.sort.should == %w(ruby scheme).sort
66
+
67
+ @taggable.reload
68
+ @taggable.all_tags_list.should include('awesome')
69
+ @taggable.all_tags_list.should include('epic')
51
70
  end
52
71
 
53
72
  it "is tagger" do
@@ -31,4 +31,8 @@ ActiveRecord::Schema.define :version => 0 do
31
31
  t.column :type, :string
32
32
  #t.column :cached_tag_list, :string
33
33
  end
34
+
35
+ create_table :untaggable_models, :force => true do |t|
36
+ t.column :name, :string
37
+ end
34
38
  end
@@ -37,10 +37,11 @@ ActiveRecord::Base.silence do
37
37
  end
38
38
 
39
39
  def clean_database!
40
- $debug = false
41
40
  models = [Tag, Tagging, TaggableModel, OtherTaggableModel, InheritingTaggableModel,
42
- AlteredInheritingTaggableModel, TaggableUser]
41
+ AlteredInheritingTaggableModel, TaggableUser, UntaggableModel]
43
42
  models.each do |model|
44
43
  model.destroy_all
45
44
  end
46
45
  end
46
+
47
+ clean_database!
metadata CHANGED
@@ -1,13 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts-as-taggable-on
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: true
5
- segments:
6
- - 2
7
- - 0
8
- - 0
9
- - pre3
10
- version: 2.0.0.pre3
4
+ version: 2.0.0.pre4
11
5
  platform: ruby
12
6
  authors:
13
7
  - Michael Bleigh
@@ -52,6 +46,7 @@ files:
52
46
  - lib/acts_as_taggable_on/tags_helper.rb
53
47
  - lib/generators/acts_as_taggable_on/migration/migration_generator.rb
54
48
  - lib/generators/acts_as_taggable_on/migration/templates/active_record/migration.rb
49
+ - rails/init.rb
55
50
  - spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb
56
51
  - spec/acts_as_taggable_on/acts_as_tagger_spec.rb
57
52
  - spec/acts_as_taggable_on/tag_list_spec.rb
@@ -77,22 +72,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
77
72
  requirements:
78
73
  - - ">="
79
74
  - !ruby/object:Gem::Version
80
- segments:
81
- - 0
82
75
  version: "0"
76
+ version:
83
77
  required_rubygems_version: !ruby/object:Gem::Requirement
84
78
  requirements:
85
79
  - - ">"
86
80
  - !ruby/object:Gem::Version
87
- segments:
88
- - 1
89
- - 3
90
- - 1
91
81
  version: 1.3.1
82
+ version:
92
83
  requirements: []
93
84
 
94
85
  rubyforge_project:
95
- rubygems_version: 1.3.6
86
+ rubygems_version: 1.3.5
96
87
  signing_key:
97
88
  specification_version: 3
98
89
  summary: ActsAsTaggableOn is a tagging plugin for Rails that provides multiple tagging contexts on a single model.