acts-as-taggable-on 2.3.1 → 2.3.2

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 CHANGED
@@ -8,3 +8,4 @@ spec/database.yml
8
8
  tmp*.sw?
9
9
  *.sw?
10
10
  tmp
11
+ *.gem
data/README.rdoc CHANGED
@@ -24,7 +24,7 @@ Not supported any more! It is time for update guys.
24
24
 
25
25
  To use it, add it to your Gemfile:
26
26
 
27
- gem 'acts-as-taggable-on', '~> 2.2.2'
27
+ gem 'acts-as-taggable-on', '~> 2.3.1'
28
28
 
29
29
  ==== Post Installation
30
30
 
@@ -20,7 +20,8 @@ module ActsAsTaggableOn
20
20
  self.remove_unused_tags = false
21
21
 
22
22
  def self.glue
23
- @@delimiter.ends_with?(" ") ? @@delimiter : "#{@@delimiter} "
23
+ delimiter = @@delimiter.kind_of?(Array) ? @@delimiter[0] : @@delimiter
24
+ delimiter.ends_with?(" ") ? delimiter : "#{delimiter} "
24
25
  end
25
26
 
26
27
  def self.setup
@@ -1,4 +1,4 @@
1
1
  module ActsAsTaggableOn
2
- VERSION = '2.3.1'
2
+ VERSION = '2.3.2'
3
3
  end
4
4
 
@@ -90,6 +90,7 @@ module ActsAsTaggableOn::Taggable
90
90
  context = options.delete(:on)
91
91
  owned_by = options.delete(:owned_by)
92
92
  alias_base_name = undecorated_table_name.gsub('.','_')
93
+ quote = ActsAsTaggableOn::Tag.using_postgresql? ? '"' : ''
93
94
 
94
95
  if options.delete(:exclude)
95
96
  if options.delete(:wild)
@@ -119,7 +120,7 @@ module ActsAsTaggableOn::Taggable
119
120
  )
120
121
 
121
122
  tagging_join = "JOIN #{ActsAsTaggableOn::Tagging.table_name} #{taggings_alias}" +
122
- " ON #{taggings_alias}.taggable_id = #{table_name}.#{primary_key}" +
123
+ " ON #{taggings_alias}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" +
123
124
  " AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name)}"
124
125
  tagging_join << " AND " + sanitize_sql(["#{taggings_alias}.context = ?", context.to_s]) if context
125
126
 
@@ -138,7 +139,7 @@ module ActsAsTaggableOn::Taggable
138
139
  taggings_alias = adjust_taggings_alias("#{alias_base_name[0..11]}_taggings_#{sha_prefix(tag.name)}")
139
140
 
140
141
  tagging_join = "JOIN #{ActsAsTaggableOn::Tagging.table_name} #{taggings_alias}" +
141
- " ON #{taggings_alias}.taggable_id = #{table_name}.#{primary_key}" +
142
+ " ON #{taggings_alias}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" +
142
143
  " AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name)}" +
143
144
  " AND #{taggings_alias}.tag_id = #{tag.id}"
144
145
  tagging_join << " AND " + sanitize_sql(["#{taggings_alias}.context = ?", context.to_s]) if context
@@ -148,7 +149,7 @@ module ActsAsTaggableOn::Taggable
148
149
  sanitize_sql([
149
150
  "#{taggings_alias}.tagger_id = ? AND #{taggings_alias}.tagger_type = ?",
150
151
  owned_by.id,
151
- owned_by.class.to_s
152
+ owned_by.class.base_class.to_s
152
153
  ])
153
154
  end
154
155
 
@@ -160,17 +161,19 @@ module ActsAsTaggableOn::Taggable
160
161
 
161
162
  if options.delete(:match_all)
162
163
  joins << "LEFT OUTER JOIN #{ActsAsTaggableOn::Tagging.table_name} #{taggings_alias}" +
163
- " ON #{taggings_alias}.taggable_id = #{table_name}.#{primary_key}" +
164
+ " ON #{taggings_alias}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" +
164
165
  " AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name)}"
165
166
 
166
167
 
167
168
  group_columns = ActsAsTaggableOn::Tag.using_postgresql? ? grouped_column_names_for(self) : "#{table_name}.#{primary_key}"
168
- group = "#{group_columns} HAVING COUNT(#{taggings_alias}.taggable_id) = #{tags.size}"
169
+ group = group_columns
170
+ having = "COUNT(#{taggings_alias}.taggable_id) = #{tags.size}"
169
171
  end
170
172
 
171
173
  scoped(:select => select_clause,
172
174
  :joins => joins.join(" "),
173
175
  :group => group,
176
+ :having => having,
174
177
  :conditions => conditions.join(" AND "),
175
178
  :order => options[:order],
176
179
  :readonly => false)
@@ -35,7 +35,7 @@ module ActsAsTaggableOn::Taggable
35
35
  else
36
36
  scope = base_tags.where([%(#{ActsAsTaggableOn::Tagging.table_name}.context = ? AND
37
37
  #{ActsAsTaggableOn::Tagging.table_name}.tagger_id = ? AND
38
- #{ActsAsTaggableOn::Tagging.table_name}.tagger_type = ?), context.to_s, owner.id, owner.class.to_s])
38
+ #{ActsAsTaggableOn::Tagging.table_name}.tagger_type = ?), context.to_s, owner.id, owner.class.base_class.to_s])
39
39
  end
40
40
  # when preserving tag order, return tags in created order
41
41
  # if we added the order to the association this would always apply
@@ -103,7 +103,7 @@ module ActsAsTaggableOn::Taggable
103
103
  # have the correct context, and are removed from the list.
104
104
  if old_tags.present?
105
105
  old_taggings = ActsAsTaggableOn::Tagging.where(:taggable_id => id, :taggable_type => self.class.base_class.to_s,
106
- :tagger_type => owner.class.to_s, :tagger_id => owner.id,
106
+ :tagger_type => owner.class.base_class.to_s, :tagger_id => owner.id,
107
107
  :tag_id => old_tags, :context => context).all
108
108
  end
109
109
 
@@ -123,4 +123,4 @@ module ActsAsTaggableOn::Taggable
123
123
  end
124
124
  end
125
125
  end
126
- end
126
+ end
@@ -21,7 +21,7 @@ module ActsAsTaggableOn
21
21
  end
22
22
 
23
23
  def self.named_any(list)
24
- where(list.map { |tag| sanitize_sql(["lower(name) = ?", tag.to_s.downcase]) }.join(" OR "))
24
+ where(list.map { |tag| sanitize_sql(["lower(name) = ?", tag.to_s.mb_chars.downcase]) }.join(" OR "))
25
25
  end
26
26
 
27
27
  def self.named_like(name)
@@ -21,10 +21,12 @@ module ActsAsTaggableOn
21
21
  string = string.to_s.dup
22
22
 
23
23
  # Parse the quoted tags
24
- string.gsub!(/(\A|#{ActsAsTaggableOn.delimiter})\s*"(.*?)"\s*(#{ActsAsTaggableOn.delimiter}\s*|\z)/) { tag_list << $2; $3 }
25
- string.gsub!(/(\A|#{ActsAsTaggableOn.delimiter})\s*'(.*?)'\s*(#{ActsAsTaggableOn.delimiter}\s*|\z)/) { tag_list << $2; $3 }
24
+ d = ActsAsTaggableOn.delimiter
25
+ d = d.join("|") if d.kind_of?(Array)
26
+ string.gsub!(/(\A|#{d})\s*"(.*?)"\s*(#{d}\s*|\z)/) { tag_list << $2; $3 }
27
+ string.gsub!(/(\A|#{d})\s*'(.*?)'\s*(#{d}\s*|\z)/) { tag_list << $2; $3 }
26
28
 
27
- tag_list.add(string.split(ActsAsTaggableOn.delimiter))
29
+ tag_list.add(string.split(Regexp.new d))
28
30
  end
29
31
  end
30
32
 
@@ -67,7 +69,9 @@ module ActsAsTaggableOn
67
69
  tags.send(:clean!)
68
70
 
69
71
  tags.map do |name|
70
- name.include?(ActsAsTaggableOn.delimiter) ? "\"#{name}\"" : name
72
+ d = ActsAsTaggableOn.delimiter
73
+ d = Regexp.new d.join("|") if d.kind_of? Array
74
+ name.index(d) ? "\"#{name}\"" : name
71
75
  end.join(ActsAsTaggableOn.glue)
72
76
  end
73
77
 
@@ -94,4 +98,4 @@ module ActsAsTaggableOn
94
98
  args.flatten!
95
99
  end
96
100
  end
97
- end
101
+ end
@@ -12,8 +12,8 @@ class ActsAsTaggableOnMigration < ActiveRecord::Migration
12
12
  t.references :taggable, :polymorphic => true
13
13
  t.references :tagger, :polymorphic => true
14
14
 
15
- # limit is created to prevent mysql error o index lenght for myisam table type.
16
- # http://bit.ly/vgW2Ql
15
+ # Limit is created to prevent MySQL error on index
16
+ # length for MyISAM table type: http://bit.ly/vgW2Ql
17
17
  t.string :context, :limit => 128
18
18
 
19
19
  t.datetime :created_at
@@ -1,3 +1,4 @@
1
+ # -*- coding: utf-8 -*-
1
2
  require File.expand_path('../../spec_helper', __FILE__)
2
3
 
3
4
  describe ActsAsTaggableOn::TagList do
@@ -90,4 +91,36 @@ describe ActsAsTaggableOn::TagList do
90
91
  end
91
92
 
92
93
  end
93
- end
94
+
95
+ describe "Multiple Delimiter" do
96
+ before do
97
+ @old_delimiter = ActsAsTaggableOn.delimiter
98
+ end
99
+
100
+ after do
101
+ ActsAsTaggableOn.delimiter = @old_delimiter
102
+ end
103
+
104
+ it "should separate tags by delimiters" do
105
+ ActsAsTaggableOn.delimiter = [',', ' ', '\|']
106
+ tag_list = ActsAsTaggableOn::TagList.from "cool, data|I have"
107
+ tag_list.to_s.should == 'cool, data, I, have'
108
+ end
109
+
110
+ it "should escape quote" do
111
+ ActsAsTaggableOn.delimiter = [',', ' ', '\|']
112
+ tag_list = ActsAsTaggableOn::TagList.from "'I have'|cool, data"
113
+ tag_list.to_s.should == '"I have", cool, data'
114
+
115
+ tag_list = ActsAsTaggableOn::TagList.from '"I, have"|cool, data'
116
+ tag_list.to_s.should == '"I, have", cool, data'
117
+ end
118
+
119
+ it "should work for utf8 delimiter and long delimiter" do
120
+ ActsAsTaggableOn.delimiter = [',', '的', '可能是']
121
+ tag_list = ActsAsTaggableOn::TagList.from "我的东西可能是不见了,还好有备份"
122
+ tag_list.to_s.should == "我, 东西, 不见了, 还好有备份"
123
+ end
124
+ end
125
+
126
+ end
@@ -107,6 +107,32 @@ describe "Tagger" do
107
107
  lambda {
108
108
  @user.tag(@taggable, :with => 'epic', :on => :tags, :skip_save => true)
109
109
  }.should_not change(ActsAsTaggableOn::Tagging, :count)
110
+ end
110
111
 
112
+ describe "Single Table Inheritance" do
113
+ before do
114
+ @user3 = InheritingTaggableUser.create
115
+ end
116
+
117
+ it "should have taggings" do
118
+ @user3.tag(@taggable, :with=>'ruby,scheme', :on=>:tags)
119
+ @user3.owned_taggings.size == 2
120
+ end
121
+
122
+ it "should have tags" do
123
+ @user3.tag(@taggable, :with=>'ruby,scheme', :on=>:tags)
124
+ @user3.owned_tags.size == 2
125
+ end
126
+
127
+ it "should return tags for the inheriting tagger" do
128
+ @user3.tag(@taggable, :with => 'ruby, scheme', :on => :tags)
129
+ @taggable.tags_from(@user3).sort.should == %w(ruby scheme).sort
130
+ end
131
+
132
+ it "should scope objects returned by tagged_with by owners" do
133
+ @user3.tag(@taggable, :with => 'ruby, scheme', :on => :tags)
134
+ TaggableModel.tagged_with(%w(ruby scheme), :owned_by => @user3).count.should == 1
135
+ end
111
136
  end
137
+
112
138
  end
data/spec/models.rb CHANGED
@@ -30,12 +30,15 @@ class TaggableUser < ActiveRecord::Base
30
30
  acts_as_tagger
31
31
  end
32
32
 
33
+ class InheritingTaggableUser < TaggableUser
34
+ end
35
+
33
36
  class UntaggableModel < ActiveRecord::Base
34
37
  belongs_to :taggable_model
35
38
  end
36
39
 
37
40
  class NonStandardIdTaggableModel < ActiveRecord::Base
38
- set_primary_key "an_id"
41
+ primary_key = "an_id"
39
42
  acts_as_taggable
40
43
  acts_as_taggable_on :languages
41
44
  acts_as_taggable_on :skills
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts-as-taggable-on
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.1
4
+ version: 2.3.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-05-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
16
- requirement: &70289733250580 !ruby/object:Gem::Requirement
16
+ requirement: &70159399452180 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '3.0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70289733250580
24
+ version_requirements: *70159399452180
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &70289733250080 !ruby/object:Gem::Requirement
27
+ requirement: &70159399451660 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '2.6'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70289733250080
35
+ version_requirements: *70159399451660
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: ammeter
38
- requirement: &70289733265980 !ruby/object:Gem::Requirement
38
+ requirement: &70159399451200 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 0.1.3
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70289733265980
46
+ version_requirements: *70159399451200
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: sqlite3
49
- requirement: &70289733265560 !ruby/object:Gem::Requirement
49
+ requirement: &70159399450820 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70289733265560
57
+ version_requirements: *70159399450820
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: mysql2
60
- requirement: &70289733264720 !ruby/object:Gem::Requirement
60
+ requirement: &70159399466580 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: 0.3.7
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70289733264720
68
+ version_requirements: *70159399466580
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: pg
71
- requirement: &70289733264020 !ruby/object:Gem::Requirement
71
+ requirement: &70159399465880 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70289733264020
79
+ version_requirements: *70159399465880
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: guard
82
- requirement: &70289733263160 !ruby/object:Gem::Requirement
82
+ requirement: &70159399465200 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70289733263160
90
+ version_requirements: *70159399465200
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: guard-rspec
93
- requirement: &70289733262700 !ruby/object:Gem::Requirement
93
+ requirement: &70159399464400 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,7 +98,7 @@ dependencies:
98
98
  version: '0'
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *70289733262700
101
+ version_requirements: *70159399464400
102
102
  description: With ActsAsTaggableOn, you can tag a single model on several contexts,
103
103
  such as skills, interests, and awards. It also provides other advanced functionality.
104
104
  email: michael@intridea.com
@@ -164,7 +164,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
164
164
  version: '0'
165
165
  segments:
166
166
  - 0
167
- hash: -1337901759790366478
167
+ hash: -4435573899217005925
168
168
  required_rubygems_version: !ruby/object:Gem::Requirement
169
169
  none: false
170
170
  requirements:
@@ -173,7 +173,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
173
173
  version: '0'
174
174
  segments:
175
175
  - 0
176
- hash: -1337901759790366478
176
+ hash: -4435573899217005925
177
177
  requirements: []
178
178
  rubyforge_project:
179
179
  rubygems_version: 1.8.10