acts-as-taggable-on 2.2.0 → 2.2.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/README.rdoc +16 -3
- data/acts-as-taggable-on.gemspec +2 -2
- data/lib/acts-as-taggable-on/version.rb +1 -1
- data/lib/acts-as-taggable-on.rb +4 -2
- data/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb +7 -19
- data/lib/acts_as_taggable_on/acts_as_taggable_on/core.rb +16 -8
- data/lib/acts_as_taggable_on/acts_as_taggable_on/related.rb +1 -1
- data/lib/acts_as_taggable_on/tag.rb +3 -0
- data/lib/acts_as_taggable_on/tagging.rb +12 -0
- data/lib/acts_as_taggable_on/tags_helper.rb +2 -2
- data/lib/acts_as_taggable_on/utils.rb +4 -0
- data/lib/generators/acts_as_taggable_on/migration/templates/active_record/migration.rb +3 -1
- data/spec/acts_as_taggable_on/tag_spec.rb +33 -10
- data/spec/acts_as_taggable_on/taggable_spec.rb +17 -15
- data/spec/acts_as_taggable_on/tagging_spec.rb +2 -5
- data/spec/acts_as_taggable_on/tags_helper_spec.rb +16 -0
- metadata +24 -24
- /data/lib/acts_as_taggable_on/{acts_as_taggable_on.rb → taggable.rb} +0 -0
- /data/lib/acts_as_taggable_on/{acts_as_tagger.rb → tagger.rb} +0 -0
data/README.rdoc
CHANGED
|
@@ -20,13 +20,13 @@ was used.
|
|
|
20
20
|
|
|
21
21
|
To use it, add it to your Gemfile:
|
|
22
22
|
|
|
23
|
-
gem 'acts-as-taggable-on', '2.1.0'
|
|
23
|
+
gem 'acts-as-taggable-on', '~>2.1.0'
|
|
24
24
|
|
|
25
25
|
=== Rails 3.x
|
|
26
26
|
|
|
27
27
|
To use it, add it to your Gemfile:
|
|
28
28
|
|
|
29
|
-
gem 'acts-as-taggable-on'
|
|
29
|
+
gem 'acts-as-taggable-on', '~>2.2.0'
|
|
30
30
|
|
|
31
31
|
==== Post Installation
|
|
32
32
|
|
|
@@ -81,10 +81,15 @@ compatibility with the will_paginate gem:
|
|
|
81
81
|
# Find a user with any of the tags:
|
|
82
82
|
User.tagged_with(["awesome", "cool"], :any => true)
|
|
83
83
|
|
|
84
|
+
# Find a user that not tags with awesome or cool:
|
|
85
|
+
User.tagged_with(["awesome", "cool"], :exclude => true)
|
|
86
|
+
|
|
84
87
|
# Find a user with any of tags based on context:
|
|
85
88
|
User.tagged_with(['awesome, cool'], :on => :tags, :any => true).tagged_with(['smart', 'shy'], :on => :skills, :any => true)
|
|
86
89
|
|
|
87
|
-
|
|
90
|
+
You can also use :wild => true option along with :any or :exclude option. It will looking for %awesome% and %cool% in sql.
|
|
91
|
+
|
|
92
|
+
Tip: User.tagged_with([]) or '' will return [], but not all records.
|
|
88
93
|
|
|
89
94
|
=== Relationships
|
|
90
95
|
|
|
@@ -177,6 +182,14 @@ CSS:
|
|
|
177
182
|
.css3 { font-size: 1.4em; }
|
|
178
183
|
.css4 { font-size: 1.6em; }
|
|
179
184
|
|
|
185
|
+
== Remove unused tags
|
|
186
|
+
|
|
187
|
+
If you would like to remove unused tag objects after removing taggings, add
|
|
188
|
+
|
|
189
|
+
ActsAsTaggableOn::Tag.remove_unused = true
|
|
190
|
+
|
|
191
|
+
to initializer file.
|
|
192
|
+
|
|
180
193
|
== Contributors
|
|
181
194
|
|
|
182
195
|
We have a long list of valued contributors. {Check them all}[https://github.com/mbleigh/acts-as-taggable-on/contributors]
|
data/acts-as-taggable-on.gemspec
CHANGED
|
@@ -4,13 +4,13 @@ require 'acts-as-taggable-on/version'
|
|
|
4
4
|
Gem::Specification.new do |gem|
|
|
5
5
|
gem.name = %q{acts-as-taggable-on}
|
|
6
6
|
gem.authors = ["Michael Bleigh"]
|
|
7
|
-
gem.date = %q{
|
|
7
|
+
gem.date = %q{2012-01-06}
|
|
8
8
|
gem.description = %q{With ActsAsTaggableOn, you can tag a single model on several contexts, such as skills, interests, and awards. It also provides other advanced functionality.}
|
|
9
9
|
gem.summary = "Advanced tagging for Rails."
|
|
10
10
|
gem.email = %q{michael@intridea.com}
|
|
11
11
|
gem.homepage = ''
|
|
12
12
|
|
|
13
|
-
gem.add_runtime_dependency 'rails', '~> 3.
|
|
13
|
+
gem.add_runtime_dependency 'rails', '~> 3.0'
|
|
14
14
|
gem.add_development_dependency 'rspec', '~> 2.5'
|
|
15
15
|
gem.add_development_dependency 'ammeter', '~> 0.1.3'
|
|
16
16
|
gem.add_development_dependency 'sqlite3'
|
data/lib/acts-as-taggable-on.rb
CHANGED
|
@@ -2,18 +2,20 @@ require "active_record"
|
|
|
2
2
|
require "active_record/version"
|
|
3
3
|
require "action_view"
|
|
4
4
|
|
|
5
|
+
require "digest/sha1"
|
|
6
|
+
|
|
5
7
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
6
8
|
|
|
7
9
|
require "acts_as_taggable_on/utils"
|
|
8
10
|
|
|
9
|
-
require "acts_as_taggable_on/
|
|
11
|
+
require "acts_as_taggable_on/taggable"
|
|
10
12
|
require "acts_as_taggable_on/acts_as_taggable_on/core"
|
|
11
13
|
require "acts_as_taggable_on/acts_as_taggable_on/collection"
|
|
12
14
|
require "acts_as_taggable_on/acts_as_taggable_on/cache"
|
|
13
15
|
require "acts_as_taggable_on/acts_as_taggable_on/ownership"
|
|
14
16
|
require "acts_as_taggable_on/acts_as_taggable_on/related"
|
|
15
17
|
|
|
16
|
-
require "acts_as_taggable_on/
|
|
18
|
+
require "acts_as_taggable_on/tagger"
|
|
17
19
|
require "acts_as_taggable_on/tag"
|
|
18
20
|
require "acts_as_taggable_on/tag_list"
|
|
19
21
|
require "acts_as_taggable_on/tags_helper"
|
|
@@ -53,11 +53,7 @@ module ActsAsTaggableOn::Taggable
|
|
|
53
53
|
def all_tag_counts(options = {})
|
|
54
54
|
options.assert_valid_keys :start_at, :end_at, :conditions, :at_least, :at_most, :order, :limit, :on, :id
|
|
55
55
|
|
|
56
|
-
scope =
|
|
57
|
-
{}
|
|
58
|
-
else
|
|
59
|
-
scope(:find) || {}
|
|
60
|
-
end
|
|
56
|
+
scope = {}
|
|
61
57
|
|
|
62
58
|
## Generate conditions:
|
|
63
59
|
options[:conditions] = sanitize_sql(options[:conditions]) if options[:conditions]
|
|
@@ -92,8 +88,6 @@ module ActsAsTaggableOn::Taggable
|
|
|
92
88
|
tag_joins = [
|
|
93
89
|
].compact
|
|
94
90
|
|
|
95
|
-
[tagging_joins, tag_joins].each(&:reverse!) if ActiveRecord::VERSION::MAJOR < 3
|
|
96
|
-
|
|
97
91
|
## Generate scope:
|
|
98
92
|
tagging_scope = ActsAsTaggableOn::Tagging.select("#{ActsAsTaggableOn::Tagging.table_name}.tag_id, COUNT(#{ActsAsTaggableOn::Tagging.table_name}.tag_id) AS tags_count")
|
|
99
93
|
tag_scope = ActsAsTaggableOn::Tag.select("#{ActsAsTaggableOn::Tag.table_name}.*, #{ActsAsTaggableOn::Tagging.table_name}.tags_count AS count").order(options[:order]).limit(options[:limit])
|
|
@@ -112,18 +106,12 @@ module ActsAsTaggableOn::Taggable
|
|
|
112
106
|
|
|
113
107
|
group_columns = "#{ActsAsTaggableOn::Tagging.table_name}.tag_id"
|
|
114
108
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
else
|
|
122
|
-
# Having is not available in 2.3.x:
|
|
123
|
-
group_by = "#{group_columns} HAVING COUNT(*) > 0"
|
|
124
|
-
group_by << " AND #{having}" unless having.blank?
|
|
125
|
-
tagging_scope = tagging_scope.group(group_by)
|
|
126
|
-
end
|
|
109
|
+
# Append the current scope to the scope, because we can't use scope(:find) in RoR 3.0 anymore:
|
|
110
|
+
scoped_select = "#{table_name}.#{primary_key}"
|
|
111
|
+
tagging_scope = tagging_scope.where("#{ActsAsTaggableOn::Tagging.table_name}.taggable_id IN(#{select(scoped_select).to_sql})").
|
|
112
|
+
group(group_columns).
|
|
113
|
+
having(having)
|
|
114
|
+
|
|
127
115
|
|
|
128
116
|
tag_scope = tag_scope.joins("JOIN (#{tagging_scope.to_sql}) AS #{ActsAsTaggableOn::Tagging.table_name} ON #{ActsAsTaggableOn::Tagging.table_name}.tag_id = #{ActsAsTaggableOn::Tag.table_name}.id")
|
|
129
117
|
tag_scope
|
|
@@ -81,20 +81,29 @@ module ActsAsTaggableOn::Taggable
|
|
|
81
81
|
alias_base_name = undecorated_table_name.gsub('.','_')
|
|
82
82
|
|
|
83
83
|
if options.delete(:exclude)
|
|
84
|
-
|
|
84
|
+
if options.delete(:wild)
|
|
85
|
+
tags_conditions = tag_list.map { |t| sanitize_sql(["#{ActsAsTaggableOn::Tag.table_name}.name #{like_operator} ? ESCAPE '!'", "%#{escape_like(t)}%"]) }.join(" OR ")
|
|
86
|
+
else
|
|
87
|
+
tags_conditions = tag_list.map { |t| sanitize_sql(["#{ActsAsTaggableOn::Tag.table_name}.name #{like_operator} ?", t]) }.join(" OR ")
|
|
88
|
+
end
|
|
89
|
+
|
|
85
90
|
conditions << "#{table_name}.#{primary_key} NOT IN (SELECT #{ActsAsTaggableOn::Tagging.table_name}.taggable_id FROM #{ActsAsTaggableOn::Tagging.table_name} JOIN #{ActsAsTaggableOn::Tag.table_name} ON #{ActsAsTaggableOn::Tagging.table_name}.tag_id = #{ActsAsTaggableOn::Tag.table_name}.#{ActsAsTaggableOn::Tag.primary_key} AND (#{tags_conditions}) WHERE #{ActsAsTaggableOn::Tagging.table_name}.taggable_type = #{quote_value(base_class.name)})"
|
|
86
91
|
|
|
87
92
|
elsif options.delete(:any)
|
|
88
93
|
# get tags, drop out if nothing returned (we need at least one)
|
|
89
|
-
|
|
94
|
+
if options.delete(:wild)
|
|
95
|
+
tags = ActsAsTaggableOn::Tag.named_like_any(tag_list)
|
|
96
|
+
else
|
|
97
|
+
tags = ActsAsTaggableOn::Tag.named_any(tag_list)
|
|
98
|
+
end
|
|
99
|
+
|
|
90
100
|
return scoped(:conditions => "1 = 0") unless tags.length > 0
|
|
91
101
|
|
|
92
102
|
# setup taggings alias so we can chain, ex: items_locations_taggings_awesome_cool_123
|
|
93
103
|
# avoid ambiguous column name
|
|
94
104
|
taggings_context = context ? "_#{context}" : ''
|
|
95
105
|
|
|
96
|
-
#
|
|
97
|
-
taggings_alias = "#{alias_base_name}#{taggings_context}_taggings_#{tags.map(&:safe_name).join('_')}_#{rand(1024)}"
|
|
106
|
+
taggings_alias = "#{alias_base_name[0..4]}#{taggings_context[0..6]}_taggings_#{sha_prefix(tags.map(&:safe_name).join('_'))}"
|
|
98
107
|
|
|
99
108
|
tagging_join = "JOIN #{ActsAsTaggableOn::Tagging.table_name} #{taggings_alias}" +
|
|
100
109
|
" ON #{taggings_alias}.taggable_id = #{table_name}.#{primary_key}" +
|
|
@@ -108,13 +117,12 @@ module ActsAsTaggableOn::Taggable
|
|
|
108
117
|
joins << tagging_join
|
|
109
118
|
|
|
110
119
|
else
|
|
111
|
-
tags = ActsAsTaggableOn::Tag.named_any(tag_list)
|
|
112
|
-
return empty_result unless tags.length == tag_list.length
|
|
120
|
+
tags = ActsAsTaggableOn::Tag.named_any(tag_list)
|
|
121
|
+
return empty_result unless tags.length == tag_list.length
|
|
113
122
|
|
|
114
123
|
tags.each do |tag|
|
|
115
|
-
prefix = "#{tag.safe_name}_#{rand(1024)}"
|
|
116
124
|
|
|
117
|
-
taggings_alias = "#{alias_base_name}_taggings_#{
|
|
125
|
+
taggings_alias = "#{alias_base_name[0..11]}_taggings_#{sha_prefix(tag.safe_name)}"
|
|
118
126
|
|
|
119
127
|
tagging_join = "JOIN #{ActsAsTaggableOn::Tagging.table_name} #{taggings_alias}" +
|
|
120
128
|
" ON #{taggings_alias}.taggable_id = #{table_name}.#{primary_key}" +
|
|
@@ -60,7 +60,7 @@ module ActsAsTaggableOn::Taggable
|
|
|
60
60
|
|
|
61
61
|
exclude_self = "#{klass.table_name}.#{klass.primary_key} != #{id} AND" if [self.class.base_class, self.class].include? klass
|
|
62
62
|
|
|
63
|
-
group_columns = ActsAsTaggableOn::Tag.using_postgresql? ? grouped_column_names_for(klass) : "#{klass.table_name}.#{klass.primary_key}"
|
|
63
|
+
group_columns = ActsAsTaggableOn::Tag.using_postgresql? ? grouped_column_names_for(klass) : "#{klass.table_name}.#{klass.primary_key}"
|
|
64
64
|
|
|
65
65
|
klass.scoped({ :select => "#{klass.table_name}.*, COUNT(#{ActsAsTaggableOn::Tag.table_name}.#{ActsAsTaggableOn::Tag.primary_key}) AS count",
|
|
66
66
|
:from => "#{klass.table_name}, #{ActsAsTaggableOn::Tag.table_name}, #{ActsAsTaggableOn::Tagging.table_name}",
|
|
@@ -18,5 +18,17 @@ module ActsAsTaggableOn
|
|
|
18
18
|
validates_presence_of :tag_id
|
|
19
19
|
|
|
20
20
|
validates_uniqueness_of :tag_id, :scope => [ :taggable_type, :taggable_id, :context, :tagger_id, :tagger_type ]
|
|
21
|
+
|
|
22
|
+
after_destroy :remove_unused_tags
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def remove_unused_tags
|
|
27
|
+
if Tag.remove_unused
|
|
28
|
+
if tag.taggings.count.zero?
|
|
29
|
+
tag.destroy
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
21
33
|
end
|
|
22
34
|
end
|
|
@@ -9,8 +9,8 @@ module ActsAsTaggableOn
|
|
|
9
9
|
max_count = tags.sort_by(&:count).last.count.to_f
|
|
10
10
|
|
|
11
11
|
tags.each do |tag|
|
|
12
|
-
index = ((tag.count / max_count) * (classes.size - 1))
|
|
13
|
-
yield tag, classes[index]
|
|
12
|
+
index = ((tag.count / max_count) * (classes.size - 1))
|
|
13
|
+
yield tag, classes[index.nan? ? 0 : index.round]
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
end
|
|
@@ -15,6 +15,10 @@ module ActsAsTaggableOn
|
|
|
15
15
|
::ActiveRecord::Base.connection && ::ActiveRecord::Base.connection.adapter_name == 'SQLite'
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
+
def sha_prefix(string)
|
|
19
|
+
Digest::SHA1.hexdigest(string + Time.now.to_s)[0..6]
|
|
20
|
+
end
|
|
21
|
+
|
|
18
22
|
private
|
|
19
23
|
def like_operator
|
|
20
24
|
using_postgresql? ? 'ILIKE' : 'LIKE'
|
|
@@ -12,7 +12,9 @@ class ActsAsTaggableOnMigration < ActiveRecord::Migration
|
|
|
12
12
|
t.references :taggable, :polymorphic => true
|
|
13
13
|
t.references :tagger, :polymorphic => true
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
# limit is created to prevent mysql error o index lenght for myisam table type.
|
|
16
|
+
# http://bit.ly/vgW2Ql
|
|
17
|
+
t.string :context, :limit => 128
|
|
16
18
|
|
|
17
19
|
t.datetime :created_at
|
|
18
20
|
end
|
|
@@ -74,20 +74,12 @@ describe ActsAsTaggableOn::Tag do
|
|
|
74
74
|
it "should require a name" do
|
|
75
75
|
@tag.valid?
|
|
76
76
|
|
|
77
|
-
|
|
78
|
-
@tag.errors[:name].should == ["can't be blank"]
|
|
79
|
-
else
|
|
80
|
-
@tag.errors[:name].should == "can't be blank"
|
|
81
|
-
end
|
|
77
|
+
@tag.errors[:name].should == ["can't be blank"]
|
|
82
78
|
|
|
83
79
|
@tag.name = "something"
|
|
84
80
|
@tag.valid?
|
|
85
81
|
|
|
86
|
-
|
|
87
|
-
@tag.errors[:name].should == []
|
|
88
|
-
else
|
|
89
|
-
@tag.errors[:name].should be_nil
|
|
90
|
-
end
|
|
82
|
+
@tag.errors[:name].should == []
|
|
91
83
|
end
|
|
92
84
|
|
|
93
85
|
it "should equal a tag with the same name" do
|
|
@@ -128,4 +120,35 @@ describe ActsAsTaggableOn::Tag do
|
|
|
128
120
|
end
|
|
129
121
|
|
|
130
122
|
end
|
|
123
|
+
|
|
124
|
+
describe ".remove_unused" do
|
|
125
|
+
before do
|
|
126
|
+
@taggable = TaggableModel.create(:name => "Bob Jones")
|
|
127
|
+
@tag = ActsAsTaggableOn::Tag.create(:name => "awesome")
|
|
128
|
+
|
|
129
|
+
@tagging = ActsAsTaggableOn::Tagging.create(:taggable => @taggable, :tag => @tag, :context => 'tags')
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
context "if set to true" do
|
|
133
|
+
before do
|
|
134
|
+
ActsAsTaggableOn::Tag.remove_unused = true
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it "should remove unused tags after removing taggings" do
|
|
138
|
+
@tagging.destroy
|
|
139
|
+
ActsAsTaggableOn::Tag.find_by_name("awesome").should be_nil
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
context "if set to false" do
|
|
144
|
+
before do
|
|
145
|
+
ActsAsTaggableOn::Tag.remove_unused = false
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it "should not remove unused tags after removing taggings" do
|
|
149
|
+
@tagging.destroy
|
|
150
|
+
ActsAsTaggableOn::Tag.find_by_name("awesome").should == @tag
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
131
154
|
end
|
|
@@ -142,20 +142,9 @@ describe "Taggable" do
|
|
|
142
142
|
TaggableModel.tagged_with(['rails, css'], :on => :needs, :any => true).tagged_with(['c++', 'java'], :on => :offerings, :any => true).to_a.should == [bob]
|
|
143
143
|
end
|
|
144
144
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
TaggableModel.tagged_with("ruby").first.should_not be_readonly
|
|
149
|
-
end
|
|
150
|
-
else
|
|
151
|
-
xit "should not return read-only records" do
|
|
152
|
-
# apparantly, there is no way to set readonly to false in a scope if joins are made
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
it "should be possible to return writable records" do
|
|
156
|
-
TaggableModel.create(:name => "Bob", :tag_list => "ruby, rails, css")
|
|
157
|
-
TaggableModel.tagged_with("ruby").first(:readonly => false).should_not be_readonly
|
|
158
|
-
end
|
|
145
|
+
it "should not return read-only records" do
|
|
146
|
+
TaggableModel.create(:name => "Bob", :tag_list => "ruby, rails, css")
|
|
147
|
+
TaggableModel.tagged_with("ruby").first.should_not be_readonly
|
|
159
148
|
end
|
|
160
149
|
|
|
161
150
|
it "should be able to get scoped tag counts" do
|
|
@@ -229,12 +218,25 @@ describe "Taggable" do
|
|
|
229
218
|
TaggableModel.tagged_with(["depressed", "css"], :order => 'taggable_models.name', :any => true).to_a.should == [bob, frank]
|
|
230
219
|
end
|
|
231
220
|
|
|
221
|
+
context "wild: true" do
|
|
222
|
+
it "should use params as wildcards" do
|
|
223
|
+
bob = TaggableModel.create(:name => "Bob", :tag_list => "bob, tricia")
|
|
224
|
+
frank = TaggableModel.create(:name => "Frank", :tag_list => "bobby, jim")
|
|
225
|
+
steve = TaggableModel.create(:name => "Steve", :tag_list => "john, patricia")
|
|
226
|
+
jim = TaggableModel.create(:name => "Jim", :tag_list => "jim, steve")
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
TaggableModel.tagged_with(["bob", "tricia"], :wild => true, :any => true).to_a.should == [bob, frank, steve]
|
|
230
|
+
TaggableModel.tagged_with(["bob", "tricia"], :wild => true, :exclude => true).to_a.should == [jim]
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
232
234
|
it "should be able to find tagged on a custom tag context" do
|
|
233
235
|
bob = TaggableModel.create(:name => "Bob")
|
|
234
236
|
bob.set_tag_list_on(:rotors, "spinning, jumping")
|
|
235
237
|
bob.tag_list_on(:rotors).should == ["spinning","jumping"]
|
|
236
238
|
bob.save
|
|
237
|
-
|
|
239
|
+
|
|
238
240
|
TaggableModel.tagged_with("spinning", :on => :rotors).to_a.should == [bob]
|
|
239
241
|
end
|
|
240
242
|
|
|
@@ -13,11 +13,7 @@ describe ActsAsTaggableOn::Tagging do
|
|
|
13
13
|
|
|
14
14
|
@tagging.should_not be_valid
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
@tagging.errors[:tag_id].should == ["can't be blank"]
|
|
18
|
-
else
|
|
19
|
-
@tagging.errors[:tag_id].should == "can't be blank"
|
|
20
|
-
end
|
|
16
|
+
@tagging.errors[:tag_id].should == ["can't be blank"]
|
|
21
17
|
end
|
|
22
18
|
|
|
23
19
|
it "should not create duplicate taggings" do
|
|
@@ -28,4 +24,5 @@ describe ActsAsTaggableOn::Tagging do
|
|
|
28
24
|
2.times { ActsAsTaggableOn::Tagging.create(:taggable => @taggable, :tag => @tag, :context => 'tags') }
|
|
29
25
|
}.should change(ActsAsTaggableOn::Tagging, :count).by(1)
|
|
30
26
|
end
|
|
27
|
+
|
|
31
28
|
end
|
|
@@ -25,4 +25,20 @@ describe ActsAsTaggableOn::TagsHelper do
|
|
|
25
25
|
tags["c++"].should == "sucky"
|
|
26
26
|
tags["php"].should == "sucky"
|
|
27
27
|
end
|
|
28
|
+
|
|
29
|
+
it "should handle tags with zero counts (build for empty)" do
|
|
30
|
+
bob = ActsAsTaggableOn::Tag.create(:name => "php")
|
|
31
|
+
tom = ActsAsTaggableOn::Tag.create(:name => "java")
|
|
32
|
+
eve = ActsAsTaggableOn::Tag.create(:name => "c++")
|
|
33
|
+
|
|
34
|
+
tags = { }
|
|
35
|
+
|
|
36
|
+
@helper.tag_cloud(ActsAsTaggableOn::Tag.all, ["sucky", "awesome"]) do |tag, css_class|
|
|
37
|
+
tags[tag.name] = css_class
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
tags["java"].should == "sucky"
|
|
41
|
+
tags["c++"].should == "sucky"
|
|
42
|
+
tags["php"].should == "sucky"
|
|
43
|
+
end
|
|
28
44
|
end
|
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.2.
|
|
4
|
+
version: 2.2.2
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,22 +9,22 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date:
|
|
12
|
+
date: 2012-01-06 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: rails
|
|
16
|
-
requirement: &
|
|
16
|
+
requirement: &70356686875400 !ruby/object:Gem::Requirement
|
|
17
17
|
none: false
|
|
18
18
|
requirements:
|
|
19
19
|
- - ~>
|
|
20
20
|
- !ruby/object:Gem::Version
|
|
21
|
-
version: '3.
|
|
21
|
+
version: '3.0'
|
|
22
22
|
type: :runtime
|
|
23
23
|
prerelease: false
|
|
24
|
-
version_requirements: *
|
|
24
|
+
version_requirements: *70356686875400
|
|
25
25
|
- !ruby/object:Gem::Dependency
|
|
26
26
|
name: rspec
|
|
27
|
-
requirement: &
|
|
27
|
+
requirement: &70356686901300 !ruby/object:Gem::Requirement
|
|
28
28
|
none: false
|
|
29
29
|
requirements:
|
|
30
30
|
- - ~>
|
|
@@ -32,10 +32,10 @@ dependencies:
|
|
|
32
32
|
version: '2.5'
|
|
33
33
|
type: :development
|
|
34
34
|
prerelease: false
|
|
35
|
-
version_requirements: *
|
|
35
|
+
version_requirements: *70356686901300
|
|
36
36
|
- !ruby/object:Gem::Dependency
|
|
37
37
|
name: ammeter
|
|
38
|
-
requirement: &
|
|
38
|
+
requirement: &70356686900800 !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: *
|
|
46
|
+
version_requirements: *70356686900800
|
|
47
47
|
- !ruby/object:Gem::Dependency
|
|
48
48
|
name: sqlite3
|
|
49
|
-
requirement: &
|
|
49
|
+
requirement: &70356686900420 !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: *
|
|
57
|
+
version_requirements: *70356686900420
|
|
58
58
|
- !ruby/object:Gem::Dependency
|
|
59
59
|
name: mysql2
|
|
60
|
-
requirement: &
|
|
60
|
+
requirement: &70356686899780 !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: *
|
|
68
|
+
version_requirements: *70356686899780
|
|
69
69
|
- !ruby/object:Gem::Dependency
|
|
70
70
|
name: pg
|
|
71
|
-
requirement: &
|
|
71
|
+
requirement: &70356686899280 !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: *
|
|
79
|
+
version_requirements: *70356686899280
|
|
80
80
|
- !ruby/object:Gem::Dependency
|
|
81
81
|
name: guard
|
|
82
|
-
requirement: &
|
|
82
|
+
requirement: &70356686898580 !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: *
|
|
90
|
+
version_requirements: *70356686898580
|
|
91
91
|
- !ruby/object:Gem::Dependency
|
|
92
92
|
name: guard-rspec
|
|
93
|
-
requirement: &
|
|
93
|
+
requirement: &70356686897920 !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: *
|
|
101
|
+
version_requirements: *70356686897920
|
|
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
|
|
@@ -118,15 +118,15 @@ files:
|
|
|
118
118
|
- acts-as-taggable-on.gemspec
|
|
119
119
|
- lib/acts-as-taggable-on.rb
|
|
120
120
|
- lib/acts-as-taggable-on/version.rb
|
|
121
|
-
- lib/acts_as_taggable_on/acts_as_taggable_on.rb
|
|
122
121
|
- lib/acts_as_taggable_on/acts_as_taggable_on/cache.rb
|
|
123
122
|
- lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb
|
|
124
123
|
- lib/acts_as_taggable_on/acts_as_taggable_on/core.rb
|
|
125
124
|
- lib/acts_as_taggable_on/acts_as_taggable_on/ownership.rb
|
|
126
125
|
- lib/acts_as_taggable_on/acts_as_taggable_on/related.rb
|
|
127
|
-
- lib/acts_as_taggable_on/acts_as_tagger.rb
|
|
128
126
|
- lib/acts_as_taggable_on/tag.rb
|
|
129
127
|
- lib/acts_as_taggable_on/tag_list.rb
|
|
128
|
+
- lib/acts_as_taggable_on/taggable.rb
|
|
129
|
+
- lib/acts_as_taggable_on/tagger.rb
|
|
130
130
|
- lib/acts_as_taggable_on/tagging.rb
|
|
131
131
|
- lib/acts_as_taggable_on/tags_helper.rb
|
|
132
132
|
- lib/acts_as_taggable_on/utils.rb
|
|
@@ -163,7 +163,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
163
163
|
version: '0'
|
|
164
164
|
segments:
|
|
165
165
|
- 0
|
|
166
|
-
hash:
|
|
166
|
+
hash: -1793358145648125
|
|
167
167
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
168
168
|
none: false
|
|
169
169
|
requirements:
|
|
@@ -172,10 +172,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
172
172
|
version: '0'
|
|
173
173
|
segments:
|
|
174
174
|
- 0
|
|
175
|
-
hash:
|
|
175
|
+
hash: -1793358145648125
|
|
176
176
|
requirements: []
|
|
177
177
|
rubyforge_project:
|
|
178
|
-
rubygems_version: 1.8.
|
|
178
|
+
rubygems_version: 1.8.10
|
|
179
179
|
signing_key:
|
|
180
180
|
specification_version: 3
|
|
181
181
|
summary: Advanced tagging for Rails.
|
|
File without changes
|
|
File without changes
|