acts-as-taggable-on 2.0.6 → 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.
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.travis.yml +9 -0
- data/CHANGELOG +10 -0
- data/Gemfile +2 -9
- data/Guardfile +5 -0
- data/README.rdoc +89 -66
- data/Rakefile +9 -55
- data/acts-as-taggable-on.gemspec +28 -0
- data/lib/acts-as-taggable-on/version.rb +4 -0
- data/lib/acts-as-taggable-on.rb +33 -4
- data/lib/acts_as_taggable_on/acts_as_taggable_on/cache.rb +4 -4
- data/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb +38 -43
- data/lib/acts_as_taggable_on/acts_as_taggable_on/core.rb +146 -38
- data/lib/acts_as_taggable_on/acts_as_taggable_on/dirty.rb +37 -0
- data/lib/acts_as_taggable_on/acts_as_taggable_on/ownership.rb +36 -11
- data/lib/acts_as_taggable_on/acts_as_taggable_on/related.rb +23 -15
- data/lib/acts_as_taggable_on/tag.rb +16 -13
- data/lib/acts_as_taggable_on/tag_list.rb +13 -12
- data/lib/acts_as_taggable_on/taggable.rb +102 -0
- data/lib/acts_as_taggable_on/{acts_as_tagger.rb → tagger.rb} +3 -3
- data/lib/acts_as_taggable_on/tagging.rb +12 -2
- data/lib/acts_as_taggable_on/tags_helper.rb +2 -2
- data/lib/acts_as_taggable_on/utils.rb +34 -0
- data/lib/generators/acts_as_taggable_on/migration/migration_generator.rb +9 -2
- data/lib/generators/acts_as_taggable_on/migration/templates/active_record/migration.rb +3 -1
- data/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb +300 -54
- data/spec/acts_as_taggable_on/tag_list_spec.rb +84 -61
- data/spec/acts_as_taggable_on/tag_spec.rb +51 -13
- data/spec/acts_as_taggable_on/taggable_spec.rb +261 -34
- data/spec/acts_as_taggable_on/tagger_spec.rb +36 -15
- data/spec/acts_as_taggable_on/tagging_spec.rb +2 -5
- data/spec/acts_as_taggable_on/tags_helper_spec.rb +16 -0
- data/spec/acts_as_taggable_on/utils_spec.rb +21 -0
- data/spec/database.yml.sample +4 -2
- data/spec/generators/acts_as_taggable_on/migration/migration_generator_spec.rb +22 -0
- data/spec/models.rb +19 -1
- data/spec/schema.rb +18 -0
- data/spec/spec_helper.rb +30 -7
- data/uninstall.rb +1 -0
- metadata +137 -51
- data/VERSION +0 -1
- data/generators/acts_as_taggable_on_migration/acts_as_taggable_on_migration_generator.rb +0 -7
- data/generators/acts_as_taggable_on_migration/templates/migration.rb +0 -29
- data/lib/acts_as_taggable_on/acts_as_taggable_on.rb +0 -53
- data/lib/acts_as_taggable_on/compatibility/Gemfile +0 -8
- data/lib/acts_as_taggable_on/compatibility/active_record_backports.rb +0 -17
- data/lib/acts_as_taggable_on/compatibility/postgresql.rb +0 -44
- data/spec/database.yml +0 -17
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
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/Gemfile
CHANGED
data/Guardfile
ADDED
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.
|
19
|
+
=== Rails 2.x
|
19
20
|
|
20
|
-
|
21
|
+
Not supported any more! It is time for update guys.
|
21
22
|
|
22
|
-
|
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
|
58
|
-
directory, you can run the specs for RoR 3.
|
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.
|
@@ -96,23 +85,33 @@ This way you can mix and match to filter down your results, and it also improves
|
|
96
85
|
compatibility with the will_paginate gem:
|
97
86
|
|
98
87
|
class User < ActiveRecord::Base
|
99
|
-
acts_as_taggable_on :tags
|
100
|
-
|
88
|
+
acts_as_taggable_on :tags, :skills
|
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 =>
|
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
|
+
|
104
|
+
# Find a user with any of tags based on context:
|
105
|
+
User.tagged_with(['awesome, cool'], :on => :tags, :any => true).tagged_with(['smart', 'shy'], :on => :skills, :any => true)
|
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
|
+
|
112
111
|
=== Relationships
|
113
112
|
|
114
113
|
You can find objects of the same type based on similar tags on certain contexts.
|
115
|
-
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
|
116
115
|
matched tags.
|
117
116
|
|
118
117
|
@bobby = User.find_by_name("Bobby")
|
@@ -125,8 +124,8 @@ matched tags.
|
|
125
124
|
@tom.skill_list # => ["hacking", "jogging", "diving"]
|
126
125
|
|
127
126
|
@tom.find_related_skills # => [<User name="Bobby">,<User name="Frankie">]
|
128
|
-
@bobby.find_related_skills # => [<User name="Tom">]
|
129
|
-
@frankie.find_related_skills # => [<User name="Tom">]
|
127
|
+
@bobby.find_related_skills # => [<User name="Tom">]
|
128
|
+
@frankie.find_related_skills # => [<User name="Tom">]
|
130
129
|
|
131
130
|
=== Dynamic Tag Contexts
|
132
131
|
|
@@ -156,8 +155,25 @@ Tags can have owners:
|
|
156
155
|
@some_user.tag(@some_photo, :with => "paris, normandy", :on => :locations)
|
157
156
|
@some_user.owned_taggings
|
158
157
|
@some_user.owned_tags
|
159
|
-
@some_photo.locations_from(@some_user)
|
160
|
-
|
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
|
+
|
161
177
|
=== Tag cloud calculations
|
162
178
|
|
163
179
|
To construct tag clouds, the frequency of each tag needs to be calculated.
|
@@ -198,24 +214,31 @@ CSS:
|
|
198
214
|
.css3 { font-size: 1.4em; }
|
199
215
|
.css4 { font-size: 1.6em; }
|
200
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
|
+
|
201
232
|
== Contributors
|
202
233
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
*
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
* azabaj - Fixed migrate down
|
215
|
-
* Peter Cooper - named_scope fix
|
216
|
-
* slainer68 - STI fix
|
217
|
-
* harrylove - migration instructions and fix-ups
|
218
|
-
* lawrencepit - cached tag work
|
219
|
-
* sobrinho - fixed tag_cloud helper
|
220
|
-
|
221
|
-
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
|
data/Rakefile
CHANGED
@@ -1,59 +1,13 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
Bundler.setup :default, :development
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
Spec::Rake::SpecTask.new do |t|
|
8
|
-
t.spec_files = FileList["spec/**/*_spec.rb"]
|
9
|
-
end
|
5
|
+
desc 'Default: run specs'
|
6
|
+
task :default => :spec
|
10
7
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
t.rcov_opts = ['--exclude', 'spec']
|
15
|
-
end
|
16
|
-
|
17
|
-
rescue LoadError
|
18
|
-
# Rspec 2.0
|
19
|
-
require 'rspec/core/rake_task'
|
20
|
-
|
21
|
-
desc 'Default: run specs'
|
22
|
-
task :default => :spec
|
23
|
-
Rspec::Core::RakeTask.new do |t|
|
24
|
-
t.pattern = "spec/**/*_spec.rb"
|
25
|
-
end
|
26
|
-
|
27
|
-
Rspec::Core::RakeTask.new('rcov') do |t|
|
28
|
-
t.pattern = "spec/**/*_spec.rb"
|
29
|
-
t.rcov = true
|
30
|
-
t.rcov_opts = ['--exclude', 'spec']
|
31
|
-
end
|
32
|
-
|
33
|
-
rescue LoadError
|
34
|
-
puts "Rspec not available. Install it with: gem install rspec"
|
35
|
-
end
|
36
|
-
|
37
|
-
namespace 'rails2.3' do
|
38
|
-
task :spec do
|
39
|
-
gemfile = File.join(File.dirname(__FILE__), 'lib', 'acts_as_taggable_on', 'compatibility', 'Gemfile')
|
40
|
-
ENV['BUNDLE_GEMFILE'] = gemfile
|
41
|
-
Rake::Task['spec'].invoke
|
42
|
-
end
|
8
|
+
require 'rspec/core/rake_task'
|
9
|
+
RSpec::Core::RakeTask.new do |t|
|
10
|
+
t.pattern = "spec/**/*_spec.rb"
|
43
11
|
end
|
44
12
|
|
45
|
-
|
46
|
-
require 'jeweler'
|
47
|
-
Jeweler::Tasks.new do |gemspec|
|
48
|
-
gemspec.name = "acts-as-taggable-on"
|
49
|
-
gemspec.summary = "ActsAsTaggableOn is a tagging plugin for Rails that provides multiple tagging contexts on a single model."
|
50
|
-
gemspec.description = "With ActsAsTaggableOn, you could tag a single model on several contexts, such as skills, interests, and awards. It also provides other advanced functionality."
|
51
|
-
gemspec.email = "michael@intridea.com"
|
52
|
-
gemspec.homepage = "http://github.com/mbleigh/acts-as-taggable-on"
|
53
|
-
gemspec.authors = ["Michael Bleigh"]
|
54
|
-
gemspec.files = FileList["[A-Z]*", "{generators,lib,spec,rails}/**/*"] - FileList["**/*.log"]
|
55
|
-
end
|
56
|
-
Jeweler::GemcutterTasks.new
|
57
|
-
rescue LoadError
|
58
|
-
puts "Jeweler not available. Install it with: gem install jeweler"
|
59
|
-
end
|
13
|
+
Bundler::GemHelper.install_tasks
|
@@ -0,0 +1,28 @@
|
|
1
|
+
$:.push File.dirname(__FILE__) + '/lib'
|
2
|
+
require 'acts-as-taggable-on/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = %q{acts-as-taggable-on}
|
6
|
+
gem.authors = ["Michael Bleigh"]
|
7
|
+
gem.date = %q{2012-01-06}
|
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
|
+
gem.summary = "Advanced tagging for Rails."
|
10
|
+
gem.email = %q{michael@intridea.com}
|
11
|
+
gem.homepage = ''
|
12
|
+
|
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'
|
16
|
+
gem.add_development_dependency 'sqlite3'
|
17
|
+
gem.add_development_dependency 'mysql2', '~> 0.3.7'
|
18
|
+
gem.add_development_dependency 'pg'
|
19
|
+
gem.add_development_dependency 'guard'
|
20
|
+
gem.add_development_dependency 'guard-rspec'
|
21
|
+
|
22
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
23
|
+
gem.files = `git ls-files`.split("\n")
|
24
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
25
|
+
gem.name = "acts-as-taggable-on"
|
26
|
+
gem.require_paths = ['lib']
|
27
|
+
gem.version = ActsAsTaggableOn::VERSION
|
28
|
+
end
|
data/lib/acts-as-taggable-on.rb
CHANGED
@@ -1,18 +1,45 @@
|
|
1
1
|
require "active_record"
|
2
|
+
require "active_record/version"
|
2
3
|
require "action_view"
|
3
4
|
|
5
|
+
require "digest/sha1"
|
6
|
+
|
4
7
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
5
8
|
|
6
|
-
|
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
|
+
|
31
|
+
|
32
|
+
require "acts_as_taggable_on/utils"
|
7
33
|
|
8
|
-
require "acts_as_taggable_on/
|
34
|
+
require "acts_as_taggable_on/taggable"
|
9
35
|
require "acts_as_taggable_on/acts_as_taggable_on/core"
|
10
36
|
require "acts_as_taggable_on/acts_as_taggable_on/collection"
|
11
37
|
require "acts_as_taggable_on/acts_as_taggable_on/cache"
|
12
38
|
require "acts_as_taggable_on/acts_as_taggable_on/ownership"
|
13
39
|
require "acts_as_taggable_on/acts_as_taggable_on/related"
|
40
|
+
require "acts_as_taggable_on/acts_as_taggable_on/dirty"
|
14
41
|
|
15
|
-
require "acts_as_taggable_on/
|
42
|
+
require "acts_as_taggable_on/tagger"
|
16
43
|
require "acts_as_taggable_on/tag"
|
17
44
|
require "acts_as_taggable_on/tag_list"
|
18
45
|
require "acts_as_taggable_on/tags_helper"
|
@@ -20,6 +47,7 @@ require "acts_as_taggable_on/tagging"
|
|
20
47
|
|
21
48
|
$LOAD_PATH.shift
|
22
49
|
|
50
|
+
|
23
51
|
if defined?(ActiveRecord::Base)
|
24
52
|
ActiveRecord::Base.extend ActsAsTaggableOn::Taggable
|
25
53
|
ActiveRecord::Base.send :include, ActsAsTaggableOn::Tagger
|
@@ -27,4 +55,5 @@ end
|
|
27
55
|
|
28
56
|
if defined?(ActionView::Base)
|
29
57
|
ActionView::Base.send :include, ActsAsTaggableOn::TagsHelper
|
30
|
-
end
|
58
|
+
end
|
59
|
+
|
@@ -11,11 +11,11 @@ module ActsAsTaggableOn::Taggable
|
|
11
11
|
before_save :save_cached_tag_list
|
12
12
|
end
|
13
13
|
|
14
|
-
base.
|
14
|
+
base.initialize_acts_as_taggable_on_cache
|
15
15
|
end
|
16
16
|
|
17
17
|
module ClassMethods
|
18
|
-
def
|
18
|
+
def initialize_acts_as_taggable_on_cache
|
19
19
|
tag_types.map(&:to_s).each do |tag_type|
|
20
20
|
class_eval %(
|
21
21
|
def self.caching_#{tag_type.singularize}_list?
|
@@ -27,7 +27,7 @@ module ActsAsTaggableOn::Taggable
|
|
27
27
|
|
28
28
|
def acts_as_taggable_on(*args)
|
29
29
|
super(*args)
|
30
|
-
|
30
|
+
initialize_acts_as_taggable_on_cache
|
31
31
|
end
|
32
32
|
|
33
33
|
def caching_tag_list_on?(context)
|
@@ -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
|
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,73 +53,68 @@ 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]
|
64
|
-
|
60
|
+
|
65
61
|
start_at_conditions = sanitize_sql(["#{ActsAsTaggableOn::Tagging.table_name}.created_at >= ?", options.delete(:start_at)]) if options[:start_at]
|
66
62
|
end_at_conditions = sanitize_sql(["#{ActsAsTaggableOn::Tagging.table_name}.created_at <= ?", options.delete(:end_at)]) if options[:end_at]
|
67
|
-
|
63
|
+
|
68
64
|
taggable_conditions = sanitize_sql(["#{ActsAsTaggableOn::Tagging.table_name}.taggable_type = ?", base_class.name])
|
69
|
-
taggable_conditions << sanitize_sql([" AND #{ActsAsTaggableOn::Tagging.table_name}.taggable_id = ?", options.delete(:id)])
|
70
|
-
|
71
|
-
|
65
|
+
taggable_conditions << sanitize_sql([" AND #{ActsAsTaggableOn::Tagging.table_name}.taggable_id = ?", options.delete(:id)]) if options[:id]
|
66
|
+
taggable_conditions << sanitize_sql([" AND #{ActsAsTaggableOn::Tagging.table_name}.context = ?", options.delete(:on).to_s]) if options[:on]
|
67
|
+
|
68
|
+
tagging_conditions = [
|
72
69
|
taggable_conditions,
|
73
|
-
options[:conditions],
|
74
70
|
scope[:conditions],
|
75
71
|
start_at_conditions,
|
76
72
|
end_at_conditions
|
77
73
|
].compact.reverse
|
78
74
|
|
75
|
+
tag_conditions = [
|
76
|
+
options[:conditions]
|
77
|
+
].compact.reverse
|
78
|
+
|
79
79
|
## Generate joins:
|
80
|
-
tagging_join = "LEFT OUTER JOIN #{ActsAsTaggableOn::Tagging.table_name} ON #{ActsAsTaggableOn::Tag.table_name}.id = #{ActsAsTaggableOn::Tagging.table_name}.tag_id"
|
81
|
-
tagging_join << sanitize_sql([" AND #{ActsAsTaggableOn::Tagging.table_name}.context = ?", options.delete(:on).to_s]) if options[:on]
|
82
|
-
|
83
80
|
taggable_join = "INNER JOIN #{table_name} ON #{table_name}.#{primary_key} = #{ActsAsTaggableOn::Tagging.table_name}.taggable_id"
|
84
81
|
taggable_join << " AND #{table_name}.#{inheritance_column} = '#{name}'" unless descends_from_active_record? # Current model is STI descendant, so add type checking to the join condition
|
85
82
|
|
86
|
-
|
87
|
-
tagging_join,
|
83
|
+
tagging_joins = [
|
88
84
|
taggable_join,
|
89
85
|
scope[:joins]
|
90
86
|
].compact
|
91
87
|
|
92
|
-
|
93
|
-
|
88
|
+
tag_joins = [
|
89
|
+
].compact
|
94
90
|
|
95
91
|
## Generate scope:
|
96
|
-
|
97
|
-
|
92
|
+
tagging_scope = ActsAsTaggableOn::Tagging.select("#{ActsAsTaggableOn::Tagging.table_name}.tag_id, COUNT(#{ActsAsTaggableOn::Tagging.table_name}.tag_id) AS tags_count")
|
93
|
+
tag_scope = ActsAsTaggableOn::Tag.select("#{ActsAsTaggableOn::Tag.table_name}.*, #{ActsAsTaggableOn::Tagging.table_name}.tags_count AS count").order(options[:order]).limit(options[:limit])
|
94
|
+
|
98
95
|
# Joins and conditions
|
99
|
-
|
100
|
-
|
101
|
-
|
96
|
+
tagging_joins.each { |join| tagging_scope = tagging_scope.joins(join) }
|
97
|
+
tagging_conditions.each { |condition| tagging_scope = tagging_scope.where(condition) }
|
98
|
+
|
99
|
+
tag_joins.each { |join| tag_scope = tag_scope.joins(join) }
|
100
|
+
tag_conditions.each { |condition| tag_scope = tag_scope.where(condition) }
|
101
|
+
|
102
102
|
# GROUP BY and HAVING clauses:
|
103
|
-
at_least = sanitize_sql(['
|
104
|
-
at_most = sanitize_sql(['
|
105
|
-
having = [at_least, at_most].compact.join(' AND ')
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
group_by << " AND #{having}" unless having.blank?
|
119
|
-
scope = scope.group(group_by)
|
120
|
-
end
|
121
|
-
|
122
|
-
scope
|
103
|
+
at_least = sanitize_sql(['tags_count >= ?', options.delete(:at_least)]) if options[:at_least]
|
104
|
+
at_most = sanitize_sql(['tags_count <= ?', options.delete(:at_most)]) if options[:at_most]
|
105
|
+
having = ["COUNT(#{ActsAsTaggableOn::Tagging.table_name}.tag_id) > 0", at_least, at_most].compact.join(' AND ')
|
106
|
+
|
107
|
+
group_columns = "#{ActsAsTaggableOn::Tagging.table_name}.tag_id"
|
108
|
+
|
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")
|
117
|
+
tag_scope
|
123
118
|
end
|
124
119
|
end
|
125
120
|
|