acts-as-taggable-on 2.1.0 → 2.3.0

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.
Files changed (42) hide show
  1. data/.gitignore +3 -0
  2. data/.travis.yml +1 -2
  3. data/CHANGELOG +10 -0
  4. data/README.rdoc +87 -67
  5. data/acts-as-taggable-on.gemspec +5 -4
  6. data/lib/acts-as-taggable-on/version.rb +1 -1
  7. data/lib/acts-as-taggable-on.rb +29 -6
  8. data/lib/acts_as_taggable_on/acts_as_taggable_on/cache.rb +1 -1
  9. data/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb +9 -21
  10. data/lib/acts_as_taggable_on/acts_as_taggable_on/core.rb +110 -33
  11. data/lib/acts_as_taggable_on/acts_as_taggable_on/dirty.rb +37 -0
  12. data/lib/acts_as_taggable_on/acts_as_taggable_on/ownership.rb +33 -12
  13. data/lib/acts_as_taggable_on/acts_as_taggable_on/related.rb +16 -16
  14. data/lib/acts_as_taggable_on/tag.rb +14 -18
  15. data/lib/acts_as_taggable_on/tag_list.rb +13 -12
  16. data/lib/acts_as_taggable_on/taggable.rb +102 -0
  17. data/lib/acts_as_taggable_on/{acts_as_tagger.rb → tagger.rb} +3 -3
  18. data/lib/acts_as_taggable_on/tagging.rb +12 -2
  19. data/lib/acts_as_taggable_on/tags_helper.rb +2 -2
  20. data/lib/acts_as_taggable_on/utils.rb +11 -8
  21. data/lib/generators/acts_as_taggable_on/migration/migration_generator.rb +9 -2
  22. data/lib/generators/acts_as_taggable_on/migration/templates/active_record/migration.rb +3 -1
  23. data/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb +286 -61
  24. data/spec/acts_as_taggable_on/tag_list_spec.rb +84 -61
  25. data/spec/acts_as_taggable_on/tag_spec.rb +42 -24
  26. data/spec/acts_as_taggable_on/taggable_spec.rb +234 -39
  27. data/spec/acts_as_taggable_on/tagger_spec.rb +36 -15
  28. data/spec/acts_as_taggable_on/tagging_spec.rb +2 -5
  29. data/spec/acts_as_taggable_on/tags_helper_spec.rb +16 -0
  30. data/spec/acts_as_taggable_on/utils_spec.rb +2 -3
  31. data/spec/database.yml.sample +1 -1
  32. data/spec/generators/acts_as_taggable_on/migration/migration_generator_spec.rb +22 -0
  33. data/spec/models.rb +16 -2
  34. data/spec/schema.rb +12 -0
  35. data/spec/spec_helper.rb +4 -1
  36. metadata +98 -125
  37. data/VERSION +0 -1
  38. data/generators/acts_as_taggable_on_migration/acts_as_taggable_on_migration_generator.rb +0 -7
  39. data/generators/acts_as_taggable_on_migration/templates/migration.rb +0 -29
  40. data/lib/acts_as_taggable_on/acts_as_taggable_on.rb +0 -63
  41. data/lib/acts_as_taggable_on/compatibility/Gemfile +0 -8
  42. data/lib/acts_as_taggable_on/compatibility/active_record_backports.rb +0 -21
data/.gitignore CHANGED
@@ -5,3 +5,6 @@
5
5
  .rvmrc
6
6
  Gemfile.lock
7
7
  spec/database.yml
8
+ tmp*.sw?
9
+ *.sw?
10
+ tmp
data/.travis.yml CHANGED
@@ -1,9 +1,8 @@
1
1
  script: "cp spec/database.yml.sample spec/database.yml && bundle install && bundle exec rake"
2
2
  rvm:
3
3
  - 1.8.7
4
- - ree
5
4
  - 1.9.2
6
- - rbx
5
+ - 1.9.3
7
6
  env:
8
7
  - DB=sqlite3
9
8
  - DB=mysql
data/CHANGELOG CHANGED
@@ -1,3 +1,13 @@
1
+ == 2011-08-21
2
+ * escape _ and % for mysql and postgres (@tilsammans)
3
+ * Now depends on mysql2 gem
4
+ * tagged_with :any is chainable now (@jeffreyiacono)
5
+ * tagged_with(nil) returns scoped object
6
+ * Case-insensitivity for TaggedModel.tagged_with for PostgreSQL database
7
+ * tagged_with(' ') returns scoped object
8
+ * remove warning for rails 3.1 about class_inheritable_attribute
9
+ * use ActiveRecord migration_number to avoid clashs (@atd)
10
+
1
11
  == 2010-02-17
2
12
  * Converted the plugin to be compatible with Rails3
3
13
 
data/README.rdoc CHANGED
@@ -1,4 +1,5 @@
1
1
  = ActsAsTaggableOn
2
+ {<img src="https://secure.travis-ci.org/mbleigh/acts-as-taggable-on.png" />}[http://travis-ci.org/mbleigh/acts-as-taggable-on]
2
3
 
3
4
  This plugin was originally based on Acts as Taggable on Steroids by Jonathan Viney.
4
5
  It has evolved substantially since that point, but all credit goes to him for the
@@ -15,37 +16,15 @@ was used.
15
16
 
16
17
  == Installation
17
18
 
18
- === Rails 2.3.x
19
+ === Rails 2.x
19
20
 
20
- Acts As Taggable On is tested to work in Rails 2.3.5.
21
+ Not supported any more! It is time for update guys.
21
22
 
22
- ==== Plugin
23
-
24
- Acts As Taggable On is available both as a gem and as a traditional plugin. For the
25
- traditional plugin you can install like so:
26
-
27
- script/plugin install git://github.com/mbleigh/acts-as-taggable-on.git
28
-
29
- Acts As Taggable On is also available as a gem plugin using Rails 2.1's gem dependencies.
30
- To install the gem, add this to your config/environment.rb:
31
-
32
- config.gem "acts-as-taggable-on", :source => "http://gemcutter.org", :version => '2.0.0.rc1'
33
-
34
- After that, you can run "rake gems:install" to install the gem if you don't already have it.
35
-
36
- ==== Post Installation
37
-
38
- 1. script/generate acts_as_taggable_on_migration
39
- 2. rake db:migrate
40
-
41
- === Rails 3.0
42
-
43
- Acts As Taggable On is now useable in Rails 3.0, thanks to the excellent work of Szymon Nowak
44
- and Jelle Vandebeeck.
23
+ === Rails 3.x
45
24
 
46
25
  To use it, add it to your Gemfile:
47
-
48
- gem 'acts-as-taggable-on'
26
+
27
+ gem 'acts-as-taggable-on', '~> 2.2.2'
49
28
 
50
29
  ==== Post Installation
51
30
 
@@ -54,20 +33,11 @@ To use it, add it to your Gemfile:
54
33
 
55
34
  == Testing
56
35
 
57
- Acts As Taggable On uses RSpec for its test coverage. Inside the plugin
58
- directory, you can run the specs for RoR 3.0.0 with:
36
+ Acts As Taggable On uses RSpec for its test coverage. Inside the gem
37
+ directory, you can run the specs for RoR 3.x with:
59
38
 
60
39
  rake spec
61
40
 
62
- If you want to test the plugin for Rails 2.3.x, use:
63
-
64
- rake rails2.3:spec
65
-
66
- If you already have RSpec on your application, the specs will run while using:
67
-
68
- rake spec:plugins
69
-
70
-
71
41
  == Usage
72
42
 
73
43
  class User < ActiveRecord::Base
@@ -89,6 +59,25 @@ rake spec:plugins
89
59
  User.skill_counts # => [<Tag name="joking" count=2>,<Tag name="clowning" count=1>...]
90
60
  @frankie.skill_counts
91
61
 
62
+ To preserve the order in which tags are created use acts_as_ordered_taggable:
63
+
64
+ class User < ActiveRecord::Base
65
+ # Alias for <tt>acts_as_ordered_taggable_on :tags</tt>:
66
+ acts_as_ordered_taggable
67
+ acts_as_ordered_taggable_on :skills, :interests
68
+ end
69
+
70
+ @user = User.new(:name => "Bobby")
71
+ @user.tag_list = "east, south"
72
+ @user.save
73
+
74
+ @user.tag_list = "north, east, south, west"
75
+ @user.save
76
+
77
+ @user.reload
78
+ @user.tag_list # => ["north", "east", "south", "west"]
79
+
80
+
92
81
  === Finding Tagged Objects
93
82
 
94
83
  Acts As Taggable On utilizes named_scopes to create an association for tags.
@@ -97,25 +86,32 @@ compatibility with the will_paginate gem:
97
86
 
98
87
  class User < ActiveRecord::Base
99
88
  acts_as_taggable_on :tags, :skills
100
- named_scope :by_join_date, :order => "created_at DESC"
89
+ scope :by_join_date, order("created_at DESC")
101
90
  end
102
91
 
103
92
  User.tagged_with("awesome").by_date
104
93
  User.tagged_with("awesome").by_date.paginate(:page => params[:page], :per_page => 20)
105
94
 
106
95
  # Find a user with matching all tags, not just one
107
- User.tagged_with(["awesome", "cool"], :match_all => :true)
108
-
96
+ User.tagged_with(["awesome", "cool"], :match_all => true)
97
+
109
98
  # Find a user with any of the tags:
110
99
  User.tagged_with(["awesome", "cool"], :any => true)
111
-
100
+
101
+ # Find a user that not tags with awesome or cool:
102
+ User.tagged_with(["awesome", "cool"], :exclude => true)
103
+
112
104
  # Find a user with any of tags based on context:
113
105
  User.tagged_with(['awesome, cool'], :on => :tags, :any => true).tagged_with(['smart', 'shy'], :on => :skills, :any => true)
114
-
106
+
107
+ You can also use :wild => true option along with :any or :exclude option. It will looking for %awesome% and %cool% in sql.
108
+
109
+ Tip: User.tagged_with([]) or '' will return [], but not all records.
110
+
115
111
  === Relationships
116
112
 
117
113
  You can find objects of the same type based on similar tags on certain contexts.
118
- Also, objects will be returned in descending order based on the total number of
114
+ Also, objects will be returned in descending order based on the total number of
119
115
  matched tags.
120
116
 
121
117
  @bobby = User.find_by_name("Bobby")
@@ -128,8 +124,8 @@ matched tags.
128
124
  @tom.skill_list # => ["hacking", "jogging", "diving"]
129
125
 
130
126
  @tom.find_related_skills # => [<User name="Bobby">,<User name="Frankie">]
131
- @bobby.find_related_skills # => [<User name="Tom">]
132
- @frankie.find_related_skills # => [<User name="Tom">]
127
+ @bobby.find_related_skills # => [<User name="Tom">]
128
+ @frankie.find_related_skills # => [<User name="Tom">]
133
129
 
134
130
  === Dynamic Tag Contexts
135
131
 
@@ -159,8 +155,25 @@ Tags can have owners:
159
155
  @some_user.tag(@some_photo, :with => "paris, normandy", :on => :locations)
160
156
  @some_user.owned_taggings
161
157
  @some_user.owned_tags
162
- @some_photo.locations_from(@some_user)
163
-
158
+ @some_photo.locations_from(@some_user) # => ["paris", "normandy"]
159
+ @some_photo.owner_tags_on(@some_user, :locations) # => [#<ActsAsTaggableOn::Tag id: 1, name: "paris">...]
160
+ @some_photo.owner_tags_on(nil, :locations) # => Ownerships equivalent to saying @some_photo.locations
161
+ @some_user.tag(@some_photo, :with => "paris, normandy", :on => :locations, :skip_save => true) #won't save @some_photo object
162
+
163
+ === Dirty objects
164
+
165
+ @bobby = User.find_by_name("Bobby")
166
+ @bobby.skill_list # => ["jogging", "diving"]
167
+
168
+ @boddy.skill_list_changed? #=> false
169
+ @boddy.changes #=> {}
170
+
171
+ @bobby.skill_list = "swimming"
172
+ @bobby.changes.should == {"skill_list"=>["jogging, diving", ["swimming"]]}
173
+ @boddy.skill_list_changed? #=> true
174
+
175
+ @bobby.skill_list_change.should == ["jogging, diving", ["swimming"]]
176
+
164
177
  === Tag cloud calculations
165
178
 
166
179
  To construct tag clouds, the frequency of each tag needs to be calculated.
@@ -201,24 +214,31 @@ CSS:
201
214
  .css3 { font-size: 1.4em; }
202
215
  .css4 { font-size: 1.6em; }
203
216
 
217
+ == Configuration
218
+
219
+ If you would like to remove unused tag objects after removing taggings, add
220
+
221
+ ActsAsTaggableOn.remove_unused_tags = true
222
+
223
+ If you want force tags to be saved downcased:
224
+
225
+ ActsAsTaggableOn.force_lowercase = true
226
+
227
+ If you want tags to be saved parametrized (you can redefine to_param as well):
228
+
229
+ ActsAsTaggableOn.force_parameterize = true
230
+
231
+
204
232
  == Contributors
205
233
 
206
- * TomEric (i76) - Maintainer
207
- * Michael Bleigh - Original Author
208
- * Szymon Nowak - Rails 3.0 compatibility
209
- * Jelle Vandebeeck - Rails 3.0 compatibility
210
- * Brendan Lim - Related Objects
211
- * Pradeep Elankumaran - Taggers
212
- * Sinclair Bain - Patch King
213
-
214
- === Patch Contributors
215
-
216
- * tristanzdunn - Related objects of other classes
217
- * azabaj - Fixed migrate down
218
- * Peter Cooper - named_scope fix
219
- * slainer68 - STI fix
220
- * harrylove - migration instructions and fix-ups
221
- * lawrencepit - cached tag work
222
- * sobrinho - fixed tag_cloud helper
223
-
224
- Copyright (c) 2007-2010 Michael Bleigh (http://mbleigh.com/) and Intridea Inc. (http://intridea.com/), released under the MIT license
234
+ We have a long list of valued contributors. {Check them all}[https://github.com/mbleigh/acts-as-taggable-on/contributors]
235
+
236
+ == Maintainers
237
+
238
+ * Artem Kramarenko (artemk)
239
+
240
+ == Author
241
+
242
+ * Michael Bleigh
243
+
244
+ Copyright (c) 2007-2011 Michael Bleigh (http://mbleigh.com/) and Intridea Inc. (http://intridea.com/), released under the MIT license
@@ -4,16 +4,17 @@ 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{2010-05-19}
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'
14
- gem.add_development_dependency 'rspec', '~> 2.5'
13
+ gem.add_runtime_dependency 'rails', '~> 3.0'
14
+ gem.add_development_dependency 'rspec', '~> 2.6'
15
+ gem.add_development_dependency 'ammeter', '~> 0.1.3'
15
16
  gem.add_development_dependency 'sqlite3'
16
- gem.add_development_dependency 'mysql2', '< 0.3'
17
+ gem.add_development_dependency 'mysql2', '~> 0.3.7'
17
18
  gem.add_development_dependency 'pg'
18
19
  gem.add_development_dependency 'guard'
19
20
  gem.add_development_dependency 'guard-rspec'
@@ -1,4 +1,4 @@
1
1
  module ActsAsTaggableOn
2
- VERSION = '2.1.0'
2
+ VERSION = '2.3.0'
3
3
  end
4
4
 
@@ -1,23 +1,45 @@
1
1
  require "active_record"
2
2
  require "active_record/version"
3
3
  require "action_view"
4
- RAILS_3 = ::ActiveRecord::VERSION::MAJOR >= 3
4
+
5
+ require "digest/sha1"
5
6
 
6
7
  $LOAD_PATH.unshift(File.dirname(__FILE__))
7
8
 
8
- require "acts_as_taggable_on/compatibility/active_record_backports" unless RAILS_3
9
+ module ActsAsTaggableOn
10
+ mattr_accessor :delimiter
11
+ @@delimiter = ','
12
+
13
+ mattr_accessor :force_lowercase
14
+ @@force_lowercase = false
15
+
16
+ mattr_accessor :force_parameterize
17
+ @@force_parameterize = false
18
+
19
+ mattr_accessor :remove_unused_tags
20
+ self.remove_unused_tags = false
21
+
22
+ def self.glue
23
+ @@delimiter.ends_with?(" ") ? @@delimiter : "#{@@delimiter} "
24
+ end
25
+
26
+ def self.setup
27
+ yield self
28
+ end
29
+ end
30
+
9
31
 
10
32
  require "acts_as_taggable_on/utils"
11
33
 
12
- require "acts_as_taggable_on/acts_as_taggable_on"
34
+ require "acts_as_taggable_on/taggable"
13
35
  require "acts_as_taggable_on/acts_as_taggable_on/core"
14
36
  require "acts_as_taggable_on/acts_as_taggable_on/collection"
15
37
  require "acts_as_taggable_on/acts_as_taggable_on/cache"
16
38
  require "acts_as_taggable_on/acts_as_taggable_on/ownership"
17
39
  require "acts_as_taggable_on/acts_as_taggable_on/related"
40
+ require "acts_as_taggable_on/acts_as_taggable_on/dirty"
18
41
 
19
- #require "acts_as_taggable_on/utils"
20
- require "acts_as_taggable_on/acts_as_tagger"
42
+ require "acts_as_taggable_on/tagger"
21
43
  require "acts_as_taggable_on/tag"
22
44
  require "acts_as_taggable_on/tag_list"
23
45
  require "acts_as_taggable_on/tags_helper"
@@ -33,4 +55,5 @@ end
33
55
 
34
56
  if defined?(ActionView::Base)
35
57
  ActionView::Base.send :include, ActsAsTaggableOn::TagsHelper
36
- end
58
+ end
59
+
@@ -40,7 +40,7 @@ module ActsAsTaggableOn::Taggable
40
40
  tag_types.map(&:to_s).each do |tag_type|
41
41
  if self.class.send("caching_#{tag_type.singularize}_list?")
42
42
  if tag_list_cache_set_on(tag_type)
43
- list = tag_list_cache_on(tag_type.singularize).to_a.flatten.compact.join(', ')
43
+ list = tag_list_cache_on(tag_type).to_a.flatten.compact.join(', ')
44
44
  self["cached_#{tag_type.singularize}_list"] = list
45
45
  end
46
46
  end
@@ -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 = if ActiveRecord::VERSION::MAJOR >= 3
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,20 +106,14 @@ module ActsAsTaggableOn::Taggable
112
106
 
113
107
  group_columns = "#{ActsAsTaggableOn::Tagging.table_name}.tag_id"
114
108
 
115
- if ActiveRecord::VERSION::MAJOR >= 3
116
- # Append the current scope to the scope, because we can't use scope(:find) in RoR 3.0 anymore:
117
- scoped_select = "#{table_name}.#{primary_key}"
118
- tagging_scope = tagging_scope.where("#{ActsAsTaggableOn::Tagging.table_name}.taggable_id IN(#{select(scoped_select).to_sql})").
119
- group(group_columns).
120
- having(having)
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
127
-
128
- tag_scope = tag_scope.joins("JOIN (#{tagging_scope.to_sql}) AS taggings ON taggings.tag_id = tags.id")
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
+
115
+
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
130
118
  end
131
119
  end