acts-as-taggable-on 2.0.6 → 2.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/.gitignore +8 -0
  2. data/.rspec +2 -0
  3. data/.travis.yml +9 -0
  4. data/CHANGELOG +10 -0
  5. data/Gemfile +2 -9
  6. data/Guardfile +5 -0
  7. data/README.rdoc +47 -63
  8. data/Rakefile +9 -55
  9. data/acts-as-taggable-on.gemspec +28 -0
  10. data/lib/acts-as-taggable-on/version.rb +4 -0
  11. data/lib/acts-as-taggable-on.rb +7 -3
  12. data/lib/acts_as_taggable_on/acts_as_taggable_on/cache.rb +4 -4
  13. data/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb +38 -43
  14. data/lib/acts_as_taggable_on/acts_as_taggable_on/core.rb +81 -30
  15. data/lib/acts_as_taggable_on/acts_as_taggable_on/ownership.rb +7 -3
  16. data/lib/acts_as_taggable_on/acts_as_taggable_on/related.rb +23 -15
  17. data/lib/acts_as_taggable_on/tag.rb +21 -12
  18. data/lib/acts_as_taggable_on/{acts_as_taggable_on.rb → taggable.rb} +6 -5
  19. data/lib/acts_as_taggable_on/tagging.rb +12 -2
  20. data/lib/acts_as_taggable_on/tags_helper.rb +2 -2
  21. data/lib/acts_as_taggable_on/utils.rb +34 -0
  22. data/lib/generators/acts_as_taggable_on/migration/migration_generator.rb +9 -2
  23. data/lib/generators/acts_as_taggable_on/migration/templates/active_record/migration.rb +3 -1
  24. data/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb +242 -54
  25. data/spec/acts_as_taggable_on/tag_list_spec.rb +4 -0
  26. data/spec/acts_as_taggable_on/tag_spec.rb +52 -13
  27. data/spec/acts_as_taggable_on/taggable_spec.rb +131 -35
  28. data/spec/acts_as_taggable_on/tagger_spec.rb +14 -0
  29. data/spec/acts_as_taggable_on/tagging_spec.rb +2 -5
  30. data/spec/acts_as_taggable_on/tags_helper_spec.rb +16 -0
  31. data/spec/acts_as_taggable_on/utils_spec.rb +21 -0
  32. data/spec/database.yml.sample +4 -2
  33. data/spec/generators/acts_as_taggable_on/migration/migration_generator_spec.rb +22 -0
  34. data/spec/models.rb +14 -1
  35. data/spec/schema.rb +13 -0
  36. data/spec/spec_helper.rb +27 -6
  37. data/uninstall.rb +1 -0
  38. metadata +136 -51
  39. data/VERSION +0 -1
  40. data/generators/acts_as_taggable_on_migration/acts_as_taggable_on_migration_generator.rb +0 -7
  41. data/generators/acts_as_taggable_on_migration/templates/migration.rb +0 -29
  42. data/lib/acts_as_taggable_on/compatibility/Gemfile +0 -8
  43. data/lib/acts_as_taggable_on/compatibility/active_record_backports.rb +0 -17
  44. data/lib/acts_as_taggable_on/compatibility/postgresql.rb +0 -44
  45. data/spec/database.yml +0 -17
  46. /data/lib/acts_as_taggable_on/{acts_as_tagger.rb → tagger.rb} +0 -0
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ *.log
2
+ *.sqlite3
3
+ /pkg/*
4
+ .bundle
5
+ .rvmrc
6
+ Gemfile.lock
7
+ spec/database.yml
8
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --backtrace
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ script: "cp spec/database.yml.sample spec/database.yml && bundle install && bundle exec rake"
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
6
+ env:
7
+ - DB=sqlite3
8
+ - DB=mysql
9
+ - DB=postgresql
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
@@ -1,10 +1,3 @@
1
- source :gemcutter
1
+ source 'http://rubygems.org'
2
+ gemspec
2
3
 
3
- # Rails 3.0
4
- gem 'rails', '3.0.0.beta3'
5
- gem 'rspec', '2.0.0.beta.8'
6
- gem 'sqlite3-ruby', :require => 'sqlite3'
7
- gem 'mysql'
8
- gem 'pg'
9
- gem 'jeweler'
10
- gem 'rcov'
data/Guardfile ADDED
@@ -0,0 +1,5 @@
1
+ guard 'rspec' do
2
+ watch(%r{^spec/.+_spec\.rb})
3
+ watch(%r{^lib/(.+)\.rb}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec" }
5
+ end
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
@@ -17,35 +18,15 @@ was used.
17
18
 
18
19
  === Rails 2.3.x
19
20
 
20
- Acts As Taggable On is tested to work in Rails 2.3.5.
21
-
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
21
+ To use it, add it to your Gemfile:
40
22
 
41
- === Rails 3.0
23
+ gem 'acts-as-taggable-on', '~>2.1.0'
42
24
 
43
- Acts As Taggable On is now useable in Rails 3.0, thanks to the excellent work of Szymon Nowak
44
- and Jelle Vandebeeck.
25
+ === Rails 3.x
45
26
 
46
27
  To use it, add it to your Gemfile:
47
-
48
- gem 'acts-as-taggable-on'
28
+
29
+ gem 'acts-as-taggable-on', '~>2.2.0'
49
30
 
50
31
  ==== Post Installation
51
32
 
@@ -54,20 +35,11 @@ To use it, add it to your Gemfile:
54
35
 
55
36
  == Testing
56
37
 
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:
38
+ Acts As Taggable On uses RSpec for its test coverage. Inside the gem
39
+ directory, you can run the specs for RoR 3.x with:
59
40
 
60
41
  rake spec
61
42
 
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
43
  == Usage
72
44
 
73
45
  class User < ActiveRecord::Base
@@ -96,8 +68,8 @@ This way you can mix and match to filter down your results, and it also improves
96
68
  compatibility with the will_paginate gem:
97
69
 
98
70
  class User < ActiveRecord::Base
99
- acts_as_taggable_on :tags
100
- named_scope :by_join_date, :order => "created_at DESC"
71
+ acts_as_taggable_on :tags, :skills
72
+ scope :by_join_date, order("created_at DESC")
101
73
  end
102
74
 
103
75
  User.tagged_with("awesome").by_date
@@ -105,14 +77,24 @@ compatibility with the will_paginate gem:
105
77
 
106
78
  # Find a user with matching all tags, not just one
107
79
  User.tagged_with(["awesome", "cool"], :match_all => :true)
108
-
80
+
109
81
  # Find a user with any of the tags:
110
82
  User.tagged_with(["awesome", "cool"], :any => true)
111
83
 
84
+ # Find a user that not tags with awesome or cool:
85
+ User.tagged_with(["awesome", "cool"], :exclude => true)
86
+
87
+ # Find a user with any of tags based on context:
88
+ User.tagged_with(['awesome, cool'], :on => :tags, :any => true).tagged_with(['smart', 'shy'], :on => :skills, :any => true)
89
+
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.
93
+
112
94
  === Relationships
113
95
 
114
96
  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
97
+ Also, objects will be returned in descending order based on the total number of
116
98
  matched tags.
117
99
 
118
100
  @bobby = User.find_by_name("Bobby")
@@ -125,8 +107,8 @@ matched tags.
125
107
  @tom.skill_list # => ["hacking", "jogging", "diving"]
126
108
 
127
109
  @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">]
110
+ @bobby.find_related_skills # => [<User name="Tom">]
111
+ @frankie.find_related_skills # => [<User name="Tom">]
130
112
 
131
113
  === Dynamic Tag Contexts
132
114
 
@@ -156,8 +138,10 @@ Tags can have owners:
156
138
  @some_user.tag(@some_photo, :with => "paris, normandy", :on => :locations)
157
139
  @some_user.owned_taggings
158
140
  @some_user.owned_tags
159
- @some_photo.locations_from(@some_user)
160
-
141
+ @some_photo.locations_from(@some_user) # => ["paris", "normandy"]
142
+ @some_photo.owner_tags_on(@some_user, :locations) # => [#<ActsAsTaggableOn::Tag id: 1, name: "paris">...]
143
+ @some_photo.owner_tags_on(nil, :locations) # => Ownerships equivalent to saying @some_photo.locations
144
+
161
145
  === Tag cloud calculations
162
146
 
163
147
  To construct tag clouds, the frequency of each tag needs to be calculated.
@@ -198,24 +182,24 @@ CSS:
198
182
  .css3 { font-size: 1.4em; }
199
183
  .css4 { font-size: 1.6em; }
200
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
+
201
193
  == Contributors
202
194
 
203
- * TomEric (i76) - Maintainer
204
- * Michael Bleigh - Original Author
205
- * Szymon Nowak - Rails 3.0 compatibility
206
- * Jelle Vandebeeck - Rails 3.0 compatibility
207
- * Brendan Lim - Related Objects
208
- * Pradeep Elankumaran - Taggers
209
- * Sinclair Bain - Patch King
210
-
211
- === Patch Contributors
212
-
213
- * tristanzdunn - Related objects of other classes
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
195
+ We have a long list of valued contributors. {Check them all}[https://github.com/mbleigh/acts-as-taggable-on/contributors]
196
+
197
+ == Maintainers
198
+
199
+ * Artem Kramarenko (artemk)
200
+
201
+ == Author
202
+
203
+ * Michael Bleigh
204
+
205
+ 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
- begin
2
- # Rspec 1.3.0
3
- require 'spec/rake/spectask'
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.setup :default, :development
4
4
 
5
- desc 'Default: run specs'
6
- task :default => :spec
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
- Spec::Rake::SpecTask.new('rcov') do |t|
12
- t.spec_files = FileList["spec/**/*_spec.rb"]
13
- t.rcov = true
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
- begin
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.5'
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
@@ -0,0 +1,4 @@
1
+ module ActsAsTaggableOn
2
+ VERSION = '2.2.2'
3
+ end
4
+
@@ -1,18 +1,21 @@
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
- require "acts_as_taggable_on/compatibility/active_record_backports" if ActiveRecord::VERSION::MAJOR < 3
9
+ require "acts_as_taggable_on/utils"
7
10
 
8
- require "acts_as_taggable_on/acts_as_taggable_on"
11
+ require "acts_as_taggable_on/taggable"
9
12
  require "acts_as_taggable_on/acts_as_taggable_on/core"
10
13
  require "acts_as_taggable_on/acts_as_taggable_on/collection"
11
14
  require "acts_as_taggable_on/acts_as_taggable_on/cache"
12
15
  require "acts_as_taggable_on/acts_as_taggable_on/ownership"
13
16
  require "acts_as_taggable_on/acts_as_taggable_on/related"
14
17
 
15
- require "acts_as_taggable_on/acts_as_tagger"
18
+ require "acts_as_taggable_on/tagger"
16
19
  require "acts_as_taggable_on/tag"
17
20
  require "acts_as_taggable_on/tag_list"
18
21
  require "acts_as_taggable_on/tags_helper"
@@ -20,6 +23,7 @@ require "acts_as_taggable_on/tagging"
20
23
 
21
24
  $LOAD_PATH.shift
22
25
 
26
+
23
27
  if defined?(ActiveRecord::Base)
24
28
  ActiveRecord::Base.extend ActsAsTaggableOn::Taggable
25
29
  ActiveRecord::Base.send :include, ActsAsTaggableOn::Tagger
@@ -11,11 +11,11 @@ module ActsAsTaggableOn::Taggable
11
11
  before_save :save_cached_tag_list
12
12
  end
13
13
 
14
- base.intialize_acts_as_taggable_on_cache
14
+ base.initialize_acts_as_taggable_on_cache
15
15
  end
16
16
 
17
17
  module ClassMethods
18
- def intialize_acts_as_taggable_on_cache
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
- intialize_acts_as_taggable_on_cache
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.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,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 = 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]
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)]) if options[:id]
70
-
71
- conditions = [
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
- joins = [
87
- tagging_join,
83
+ tagging_joins = [
88
84
  taggable_join,
89
85
  scope[:joins]
90
86
  ].compact
91
87
 
92
- joins = joins.reverse if ActiveRecord::VERSION::MAJOR < 3
93
-
88
+ tag_joins = [
89
+ ].compact
94
90
 
95
91
  ## Generate scope:
96
- scope = ActsAsTaggableOn::Tag.scoped(:select => "#{ActsAsTaggableOn::Tag.table_name}.*, COUNT(*) AS count").order(options[:order]).limit(options[:limit])
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
- joins.each { |join| scope = scope.joins(join) }
100
- conditions.each { |condition| scope = scope.where(condition) }
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(['COUNT(*) >= ?', options.delete(:at_least)]) if options[:at_least]
104
- at_most = sanitize_sql(['COUNT(*) <= ?', options.delete(:at_most)]) if options[:at_most]
105
- having = [at_least, at_most].compact.join(' AND ')
106
-
107
- if ActiveRecord::VERSION::MAJOR >= 3
108
- # Append the current scope to the scope, because we can't use scope(:find) in RoR 3.0 anymore:
109
- scoped_select = "#{table_name}.#{primary_key}"
110
- scope = scope.where("#{ActsAsTaggableOn::Tagging.table_name}.taggable_id IN(#{select(scoped_select).to_sql})")
111
-
112
- # We have having() in RoR 3.0 so use it:
113
- having = having.blank? ? "COUNT(*) > 0" : "COUNT(*) > 0 AND #{having}"
114
- scope = scope.group(grouped_column_names_for(ActsAsTaggableOn::Tag)).having(having)
115
- else
116
- # Having is not available in 2.3.x:
117
- group_by = "#{grouped_column_names_for(ActsAsTaggableOn::Tag)} HAVING COUNT(*) > 0"
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