acts-as-taggable-on 2.3.1 → 2.3.2

Sign up to get free protection for your applications and to get access to all the features.
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