acts-as-taggable-on 2.4.1 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +13 -4
- data/Appraisals +8 -4
- data/CHANGELOG.md +47 -0
- data/Gemfile +7 -1
- data/README.md +21 -11
- data/Rakefile +21 -3
- data/UPGRADING +7 -0
- data/acts-as-taggable-on.gemspec +5 -5
- data/{lib/generators/acts_as_taggable_on/migration/templates/active_record/migration.rb → db/migrate/1_acts_as_taggable_on_migration.rb} +0 -0
- data/db/migrate/2_add_missing_unique_indices.rb +21 -0
- data/gemfiles/{rails_3.gemfile → rails_3.2.gemfile} +1 -2
- data/gemfiles/rails_4.0.gemfile +7 -0
- data/gemfiles/rails_4.1.gemfile +7 -0
- data/lib/acts-as-taggable-on.rb +9 -13
- data/lib/acts_as_taggable_on.rb +6 -0
- data/lib/acts_as_taggable_on/acts_as_taggable_on/cache.rb +49 -20
- data/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb +42 -32
- data/lib/acts_as_taggable_on/acts_as_taggable_on/compatibility.rb +1 -1
- data/lib/acts_as_taggable_on/acts_as_taggable_on/core.rb +24 -13
- data/lib/acts_as_taggable_on/engine.rb +6 -0
- data/lib/acts_as_taggable_on/tag.rb +27 -7
- data/lib/acts_as_taggable_on/taggable.rb +6 -6
- data/lib/acts_as_taggable_on/tagger.rb +6 -6
- data/lib/acts_as_taggable_on/tags_helper.rb +1 -1
- data/lib/acts_as_taggable_on/version.rb +1 -1
- data/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb +4 -71
- data/spec/acts_as_taggable_on/acts_as_tagger_spec.rb +19 -19
- data/spec/acts_as_taggable_on/caching_spec.rb +77 -0
- data/spec/acts_as_taggable_on/tags_helper_spec.rb +10 -10
- data/spec/schema.rb +25 -21
- data/spec/spec_helper.rb +9 -25
- metadata +40 -56
- data/gemfiles/rails_4.gemfile +0 -8
- data/lib/generators/acts_as_taggable_on/migration/migration_generator.rb +0 -39
- data/spec/generators/acts_as_taggable_on/migration/migration_generator_spec.rb +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5b46e80f19a5c7de71ec448bd0700ef672ea9639
|
4
|
+
data.tar.gz: d7c19bc3aec73a2b5d1ff08ad18cb9c85e61225c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ac4317c1fa00caa6f048d4958d830da83bae5a48d8fd2f4018918319069e9e0311b99318cfe337fcd8d23f9c37055484e1c40c1ab0ecda2c256d361315b0848
|
7
|
+
data.tar.gz: 7e29cf71dfce65f2ac65d0a10972c6b26344398278c53b088b9069ec728955e697389f496b25a8f57fd521b6349aaa2ef827caab78bf8a00c7416c9be43c21e5
|
data/.travis.yml
CHANGED
@@ -1,9 +1,18 @@
|
|
1
|
-
script: "cp spec/database.yml.sample spec/database.yml && bundle install && bundle exec rake"
|
2
1
|
rvm:
|
3
|
-
- 1.8.7
|
4
|
-
- 1.9.2
|
5
2
|
- 1.9.3
|
3
|
+
- 2.0.0
|
6
4
|
env:
|
7
5
|
- DB=sqlite3
|
8
6
|
- DB=mysql
|
9
|
-
- DB=postgresql
|
7
|
+
- DB=postgresql
|
8
|
+
gemfile:
|
9
|
+
- gemfiles/rails_3.2.gemfile
|
10
|
+
- gemfiles/rails_4.0.gemfile
|
11
|
+
- gemfiles/rails_4.1.gemfile
|
12
|
+
cache: bundler
|
13
|
+
script: bundle exec rake
|
14
|
+
before_install:
|
15
|
+
- gem install bundler
|
16
|
+
bundler_args: '--without local_development'
|
17
|
+
matrix:
|
18
|
+
fast_finish: true
|
data/Appraisals
CHANGED
@@ -1,7 +1,11 @@
|
|
1
|
-
appraise "rails-3" do
|
2
|
-
gem "rails", "3.2
|
1
|
+
appraise "rails-3.2" do
|
2
|
+
gem "rails", "~> 3.2"
|
3
3
|
end
|
4
4
|
|
5
|
-
appraise "rails-4" do
|
6
|
-
gem "rails", "4.0
|
5
|
+
appraise "rails-4.0" do
|
6
|
+
gem "rails", "~> 4.0"
|
7
|
+
end
|
8
|
+
|
9
|
+
appraise "rails-4.1" do
|
10
|
+
gem "rails", "~> 4.1.0.beta1"
|
7
11
|
end
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
Changes are below categorized as `Features, Fixes, or Misc`.
|
2
|
+
|
3
|
+
Each change should fall into categories that would affect whether the release is major (breaking changes), minor (new behavior), or patch (bug fix). See [semver](http://semver.org/) and [pessimistic versioning](http://guides.rubygems.org/patterns/#pessimistic_version_constraint)
|
4
|
+
|
5
|
+
As such, a _Feature_ would map to either major or minor. A _bug fix_ to a patch. And _misc_ is either minor or patch, the difference being kind of fuzzy for the purposes of history. Adding tests would be patch level.
|
6
|
+
|
7
|
+
### Master [changes](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.0.0...master)
|
8
|
+
|
9
|
+
* Breaking Changes
|
10
|
+
* Features
|
11
|
+
* Fixes
|
12
|
+
* Misc
|
13
|
+
|
14
|
+
### [3.0.0 / 2014-01-01](https://github.com/mbleigh/acts-as-taggable-on/compare/v2.4.1...v3.0.0)
|
15
|
+
|
16
|
+
* Breaking Changes
|
17
|
+
* No longer supports Ruby 1.8.
|
18
|
+
* Features
|
19
|
+
* Supports Rails 4.1.
|
20
|
+
* Misc (TODO: expand)
|
21
|
+
* [zquest #359](https://github.com/mbleigh/acts-as-taggable-on/pull/359)
|
22
|
+
* [rsl #367](https://github.com/mbleigh/acts-as-taggable-on/pull/367)
|
23
|
+
* [ktdreyer #383](https://github.com/mbleigh/acts-as-taggable-on/pull/383)
|
24
|
+
* [cwoodcox #346](https://github.com/mbleigh/acts-as-taggable-on/pull/346)
|
25
|
+
* [mrb #421](https://github.com/mbleigh/acts-as-taggable-on/pull/421)
|
26
|
+
* [bf4 #430](https://github.com/mbleigh/acts-as-taggable-on/pull/430)
|
27
|
+
* [sanemat #368](https://github.com/mbleigh/acts-as-taggable-on/pull/368)
|
28
|
+
* [bf4 #343](https://github.com/mbleigh/acts-as-taggable-on/pull/343)
|
29
|
+
* [marclennox #429](https://github.com/mbleigh/acts-as-taggable-on/pull/429)
|
30
|
+
* [shekibobo #403](https://github.com/mbleigh/acts-as-taggable-on/pull/403)
|
31
|
+
* [ches ktdreyer #410](https://github.com/mbleigh/acts-as-taggable-on/pull/410)
|
32
|
+
* [makaroni4 #371](https://github.com/mbleigh/acts-as-taggable-on/pull/371)
|
33
|
+
* [kenzai dstosik awt #431](https://github.com/mbleigh/acts-as-taggable-on/pull/431)
|
34
|
+
* [bf4 joelcogen shekibobo aaronchi #438](https://github.com/mbleigh/acts-as-taggable-on/pull/438)
|
35
|
+
* [seuros #442](https://github.com/mbleigh/acts-as-taggable-on/pull/442)
|
36
|
+
* [bf4 #445](https://github.com/mbleigh/acts-as-taggable-on/pull/445)
|
37
|
+
* [eaglemt #446](https://github.com/mbleigh/acts-as-taggable-on/pull/446)
|
38
|
+
|
39
|
+
### 3.0.0.rc2 [changes](https://github.com/mbleigh/acts-as-taggable-on/compare/fork-v3.0.0.rc1...fork-v3.0.0.rc2)
|
40
|
+
|
41
|
+
### 3.0.0.rc1 [changes](https://github.com/mbleigh/acts-as-taggable-on/compare/v2.4.1...fork-v3.0.0.rc1)
|
42
|
+
|
43
|
+
### [2.4.1 / 2013-05-07](https://github.com/mbleigh/acts-as-taggable-on/compare/v2.4.0...v2.4.1)
|
44
|
+
|
45
|
+
* Features
|
46
|
+
* Fixes
|
47
|
+
* Misc
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# ActsAsTaggableOn
|
2
2
|
[![Build Status](https://secure.travis-ci.org/mbleigh/acts-as-taggable-on.png)](http://travis-ci.org/mbleigh/acts-as-taggable-on)
|
3
|
+
[![Code Climate](https://codeclimate.com/github/mbleigh/acts-as-taggable-on.png)](https://codeclimate.com/github/mbleigh/acts-as-taggable-on)
|
3
4
|
|
4
5
|
This plugin was originally based on Acts as Taggable on Steroids by Jonathan Viney.
|
5
6
|
It has evolved substantially since that point, but all credit goes to him for the
|
@@ -20,7 +21,7 @@ Versions 2.x are compatible with Ruby 1.8.7+ and Rails 3.
|
|
20
21
|
|
21
22
|
Versions 2.4.1 and up are compatible with Rails 4 too (thanks to arabonradar and cwoodcox).
|
22
23
|
|
23
|
-
Versions 3.x (currently unreleased) are compatible with Ruby 1.9.3+ and Rails 3 and 4.
|
24
|
+
Versions 3.x (currently unreleased) are compatible with Ruby 1.9.3+ and Rails 3 and 4. There is a [release candidate you may try](http://rubygems.org/gems/acts_as_taggable_on).
|
24
25
|
|
25
26
|
For an up-to-date roadmap, see https://github.com/mbleigh/acts-as-taggable-on/issues/milestones
|
26
27
|
|
@@ -41,21 +42,17 @@ bundle
|
|
41
42
|
#### Post Installation
|
42
43
|
|
43
44
|
```shell
|
45
|
+
# For the latest versions
|
46
|
+
rake railties:install:migrations FROM=acts_as_taggable_on_engine db:migrate
|
47
|
+
|
48
|
+
# For versions 2.4.1 and earlier
|
44
49
|
rails generate acts_as_taggable_on:migration
|
45
50
|
rake db:migrate
|
46
51
|
```
|
47
52
|
|
48
|
-
|
53
|
+
#### Upgrading
|
49
54
|
|
50
|
-
|
51
|
-
directory, you can run the specs with:
|
52
|
-
|
53
|
-
```shell
|
54
|
-
bundle
|
55
|
-
rake spec
|
56
|
-
```
|
57
|
-
|
58
|
-
If you want, add a `.ruby-version` file in the project root (and use rbenv or RVM) to work on a specific version of Ruby.
|
55
|
+
see [UPGRADING](UPGRADING)
|
59
56
|
|
60
57
|
## Usage
|
61
58
|
|
@@ -298,6 +295,19 @@ We have a long list of valued contributors. [Check them all](https://github.com/
|
|
298
295
|
|
299
296
|
* [Joost Baaij](https://github.com/tilsammans)
|
300
297
|
|
298
|
+
## Testing
|
299
|
+
|
300
|
+
Acts As Taggable On uses RSpec for its test coverage. Inside the gem
|
301
|
+
directory, you can run the specs with:
|
302
|
+
|
303
|
+
```shell
|
304
|
+
bundle
|
305
|
+
rake spec
|
306
|
+
```
|
307
|
+
|
308
|
+
You can run all the tests across all the Rails versions by running `rake appraise`. If you'd also like to [run the tests across all rubies and databases as configured for Travis CI, install and run `wwtd`](https://github.com/grosser/wwtd).
|
309
|
+
|
310
|
+
|
301
311
|
## License
|
302
312
|
|
303
313
|
See [LICENSE](https://github.com/mbleigh/acts-as-taggable-on/blob/master/LICENSE.md)
|
data/Rakefile
CHANGED
@@ -1,9 +1,27 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
|
3
|
-
require '
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
STDERR.puts "Bundler not loaded"
|
6
|
+
end
|
7
|
+
|
8
|
+
desc 'Copy sample spec database.yml over if not exists'
|
9
|
+
task :copy_db_config do
|
10
|
+
cp 'spec/database.yml.sample', 'spec/database.yml'
|
11
|
+
end
|
12
|
+
|
13
|
+
task :spec => [:copy_db_config]
|
4
14
|
|
5
15
|
desc 'Default: run specs'
|
6
|
-
task :default => :spec
|
16
|
+
task :default => :spec
|
17
|
+
|
18
|
+
begin
|
19
|
+
require 'appraisal'
|
20
|
+
desc 'Run tests across gemfiles specified in Appraisals'
|
21
|
+
task :appraise => ['appraisal:cleanup', 'appraisal:install', 'appraisal']
|
22
|
+
rescue LoadError
|
23
|
+
puts "appraisal tasks not available"
|
24
|
+
end
|
7
25
|
|
8
26
|
require 'rspec/core/rake_task'
|
9
27
|
RSpec::Core::RakeTask.new do |t|
|
data/UPGRADING
ADDED
data/acts-as-taggable-on.gemspec
CHANGED
@@ -24,12 +24,12 @@ Gem::Specification.new do |gem|
|
|
24
24
|
|
25
25
|
gem.add_runtime_dependency 'rails', ['>= 3', '< 5']
|
26
26
|
|
27
|
-
gem.add_development_dependency 'rspec-rails', '2.13.0' # 2.13.1 is broken
|
28
|
-
gem.add_development_dependency 'rspec', '~> 2.6'
|
29
|
-
gem.add_development_dependency 'ammeter'
|
30
27
|
gem.add_development_dependency 'sqlite3'
|
31
28
|
gem.add_development_dependency 'mysql2', '~> 0.3.7'
|
32
29
|
gem.add_development_dependency 'pg'
|
33
|
-
|
34
|
-
gem.add_development_dependency '
|
30
|
+
|
31
|
+
gem.add_development_dependency 'rspec-rails', '2.13.0' # 2.13.1 is broken
|
32
|
+
gem.add_development_dependency 'rspec', '~> 2.6'
|
33
|
+
gem.add_development_dependency 'ammeter'
|
34
|
+
|
35
35
|
end
|
File without changes
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class AddMissingUniqueIndices < ActiveRecord::Migration
|
2
|
+
|
3
|
+
def self.up
|
4
|
+
add_index :tags, :name, unique: true
|
5
|
+
|
6
|
+
remove_index :taggings, :tag_id
|
7
|
+
remove_index :taggings, [:taggable_id, :taggable_type, :context]
|
8
|
+
add_index :taggings,
|
9
|
+
[:tag_id, :taggable_id, :taggable_type, :context, :tagger_id, :tagger_type],
|
10
|
+
unique: true, name: 'taggings_idx'
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.down
|
14
|
+
remove_index :tags, :name
|
15
|
+
|
16
|
+
remove_index :taggings, name: 'tagging_idx'
|
17
|
+
add_index :taggings, :tag_id
|
18
|
+
add_index :taggings, [:taggable_id, :taggable_type, :context]
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
data/lib/acts-as-taggable-on.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
require "active_record"
|
2
2
|
require "active_record/version"
|
3
|
+
require "active_support/core_ext/module"
|
3
4
|
require "action_view"
|
5
|
+
require 'active_support/all'
|
4
6
|
|
5
7
|
require "digest/sha1"
|
6
8
|
|
7
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
8
|
-
|
9
9
|
module ActsAsTaggableOn
|
10
10
|
mattr_accessor :delimiter
|
11
11
|
@@delimiter = ','
|
@@ -49,17 +49,13 @@ require "acts_as_taggable_on/tag"
|
|
49
49
|
require "acts_as_taggable_on/tag_list"
|
50
50
|
require "acts_as_taggable_on/tags_helper"
|
51
51
|
require "acts_as_taggable_on/tagging"
|
52
|
+
require 'acts_as_taggable_on/engine'
|
52
53
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
ActiveRecord::Base.extend ActsAsTaggableOn::Compatibility
|
58
|
-
ActiveRecord::Base.extend ActsAsTaggableOn::Taggable
|
59
|
-
ActiveRecord::Base.send :include, ActsAsTaggableOn::Tagger
|
54
|
+
ActiveSupport.on_load(:active_record) do
|
55
|
+
extend ActsAsTaggableOn::Compatibility
|
56
|
+
extend ActsAsTaggableOn::Taggable
|
57
|
+
include ActsAsTaggableOn::Tagger
|
60
58
|
end
|
61
|
-
|
62
|
-
|
63
|
-
ActionView::Base.send :include, ActsAsTaggableOn::TagsHelper
|
59
|
+
ActiveSupport.on_load(:action_view) do
|
60
|
+
include ActsAsTaggableOn::TagsHelper
|
64
61
|
end
|
65
|
-
|
@@ -1,41 +1,69 @@
|
|
1
1
|
module ActsAsTaggableOn::Taggable
|
2
2
|
module Cache
|
3
3
|
def self.included(base)
|
4
|
-
#
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
4
|
+
# When included, conditionally adds tag caching methods when the model
|
5
|
+
# has any "cached_#{tag_type}_list" column
|
6
|
+
base.instance_eval do
|
7
|
+
# @private
|
8
|
+
def _has_tags_cache_columns?(db_columns)
|
9
|
+
db_column_names = db_columns.map(&:name)
|
10
|
+
tag_types.any? {|context|
|
11
|
+
db_column_names.include?("cached_#{context.to_s.singularize}_list")
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
# @private
|
16
|
+
def _add_tags_caching_methods
|
17
|
+
send :include, ActsAsTaggableOn::Taggable::Cache::InstanceMethods
|
18
|
+
extend ActsAsTaggableOn::Taggable::Cache::ClassMethods
|
19
|
+
|
20
|
+
before_save :save_cached_tag_list
|
21
|
+
|
22
|
+
initialize_tags_cache
|
23
|
+
end
|
24
|
+
|
25
|
+
# ActiveRecord::Base.columns makes a database connection and caches the calculated
|
26
|
+
# columns hash for the record as @columns. Since we don't want to add caching
|
27
|
+
# methods until we confirm the presence of a caching column, and we don't
|
28
|
+
# want to force opening a database connection when the class is loaded,
|
29
|
+
# here we intercept and cache the call to :columns as @acts_as_taggable_on_columns
|
30
|
+
# to mimic the underlying behavior. While processing this first call to columns,
|
31
|
+
# we do the caching column check and dynamically add the class and instance methods
|
32
|
+
def columns
|
33
|
+
@acts_as_taggable_on_columns ||= begin
|
34
|
+
db_columns = super
|
35
|
+
if _has_tags_cache_columns?(db_columns)
|
36
|
+
_add_tags_caching_methods
|
37
|
+
end
|
38
|
+
db_columns
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
12
42
|
end
|
13
|
-
|
14
|
-
base.initialize_acts_as_taggable_on_cache
|
15
43
|
end
|
16
|
-
|
44
|
+
|
17
45
|
module ClassMethods
|
18
|
-
def
|
46
|
+
def initialize_tags_cache
|
19
47
|
tag_types.map(&:to_s).each do |tag_type|
|
20
48
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
21
49
|
def self.caching_#{tag_type.singularize}_list?
|
22
50
|
caching_tag_list_on?("#{tag_type}")
|
23
|
-
end
|
51
|
+
end
|
24
52
|
RUBY
|
25
|
-
end
|
53
|
+
end
|
26
54
|
end
|
27
|
-
|
55
|
+
|
28
56
|
def acts_as_taggable_on(*args)
|
29
57
|
super(*args)
|
30
|
-
|
58
|
+
initialize_tags_cache
|
31
59
|
end
|
32
|
-
|
60
|
+
|
33
61
|
def caching_tag_list_on?(context)
|
34
62
|
column_names.include?("cached_#{context.to_s.singularize}_list")
|
35
63
|
end
|
36
64
|
end
|
37
|
-
|
38
|
-
module InstanceMethods
|
65
|
+
|
66
|
+
module InstanceMethods
|
39
67
|
def save_cached_tag_list
|
40
68
|
tag_types.map(&:to_s).each do |tag_type|
|
41
69
|
if self.class.send("caching_#{tag_type.singularize}_list?")
|
@@ -45,9 +73,10 @@ module ActsAsTaggableOn::Taggable
|
|
45
73
|
end
|
46
74
|
end
|
47
75
|
end
|
48
|
-
|
76
|
+
|
49
77
|
true
|
50
78
|
end
|
51
79
|
end
|
80
|
+
|
52
81
|
end
|
53
82
|
end
|
@@ -5,7 +5,7 @@ module ActsAsTaggableOn::Taggable
|
|
5
5
|
base.extend ActsAsTaggableOn::Taggable::Collection::ClassMethods
|
6
6
|
base.initialize_acts_as_taggable_on_collection
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
module ClassMethods
|
10
10
|
def initialize_acts_as_taggable_on_collection
|
11
11
|
tag_types.map(&:to_s).each do |tag_type|
|
@@ -24,16 +24,16 @@ module ActsAsTaggableOn::Taggable
|
|
24
24
|
|
25
25
|
def self.top_#{tag_type}(limit = 10)
|
26
26
|
tag_counts_on('#{tag_type}', :order => 'count desc', :limit => limit.to_i)
|
27
|
-
end
|
27
|
+
end
|
28
28
|
RUBY
|
29
|
-
end
|
29
|
+
end
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
def acts_as_taggable_on(*args)
|
33
33
|
super(*args)
|
34
34
|
initialize_acts_as_taggable_on_collection
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
def tag_counts_on(context, options = {})
|
38
38
|
all_tag_counts(options.merge({:on => context.to_s}))
|
39
39
|
end
|
@@ -86,12 +86,13 @@ module ActsAsTaggableOn::Taggable
|
|
86
86
|
group_columns = "#{ActsAsTaggableOn::Tagging.table_name}.tag_id"
|
87
87
|
|
88
88
|
# Append the current scope to the scope, because we can't use scope(:find) in RoR 3.0 anymore:
|
89
|
-
|
90
|
-
tagging_scope = tagging_scope.where("#{ActsAsTaggableOn::Tagging.table_name}.taggable_id IN(
|
91
|
-
|
92
|
-
tag_scope.joins("JOIN (#{tagging_scope
|
89
|
+
scoped_select = "#{table_name}.#{primary_key}"
|
90
|
+
tagging_scope = tagging_scope.where("#{ActsAsTaggableOn::Tagging.table_name}.taggable_id IN(#{safe_to_sql(select(scoped_select))})").group(group_columns)
|
91
|
+
|
92
|
+
tag_scope = tag_scope.joins("JOIN (#{safe_to_sql(tagging_scope)}) AS #{ActsAsTaggableOn::Tagging.table_name} ON #{ActsAsTaggableOn::Tagging.table_name}.tag_id = #{ActsAsTaggableOn::Tag.table_name}.id")
|
93
|
+
tag_scope.extending(CalculationMethods)
|
93
94
|
end
|
94
|
-
|
95
|
+
|
95
96
|
##
|
96
97
|
# Calculate the tag counts for all tags.
|
97
98
|
#
|
@@ -110,29 +111,29 @@ module ActsAsTaggableOn::Taggable
|
|
110
111
|
scope = {}
|
111
112
|
|
112
113
|
## Generate conditions:
|
113
|
-
options[:conditions] = sanitize_sql(options[:conditions]) if options[:conditions]
|
114
|
+
options[:conditions] = sanitize_sql(options[:conditions]) if options[:conditions]
|
114
115
|
|
115
116
|
start_at_conditions = sanitize_sql(["#{ActsAsTaggableOn::Tagging.table_name}.created_at >= ?", options.delete(:start_at)]) if options[:start_at]
|
116
117
|
end_at_conditions = sanitize_sql(["#{ActsAsTaggableOn::Tagging.table_name}.created_at <= ?", options.delete(:end_at)]) if options[:end_at]
|
117
|
-
|
118
|
+
|
118
119
|
taggable_conditions = sanitize_sql(["#{ActsAsTaggableOn::Tagging.table_name}.taggable_type = ?", base_class.name])
|
119
|
-
taggable_conditions << sanitize_sql([" AND #{ActsAsTaggableOn::Tagging.table_name}.taggable_id = ?", options
|
120
|
+
taggable_conditions << sanitize_sql([" AND #{ActsAsTaggableOn::Tagging.table_name}.taggable_id = ?", options[:id]]) if options[:id]
|
120
121
|
taggable_conditions << sanitize_sql([" AND #{ActsAsTaggableOn::Tagging.table_name}.context = ?", options.delete(:on).to_s]) if options[:on]
|
121
|
-
|
122
|
+
|
122
123
|
tagging_conditions = [
|
123
124
|
taggable_conditions,
|
124
125
|
scope[:conditions],
|
125
126
|
start_at_conditions,
|
126
127
|
end_at_conditions
|
127
128
|
].compact.reverse
|
128
|
-
|
129
|
+
|
129
130
|
tag_conditions = [
|
130
|
-
options[:conditions]
|
131
|
+
options[:conditions]
|
131
132
|
].compact.reverse
|
132
|
-
|
133
|
+
|
133
134
|
## Generate joins:
|
134
135
|
taggable_join = "INNER JOIN #{table_name} ON #{table_name}.#{primary_key} = #{ActsAsTaggableOn::Tagging.table_name}.taggable_id"
|
135
|
-
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
|
136
|
+
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
|
136
137
|
|
137
138
|
tagging_joins = [
|
138
139
|
taggable_join,
|
@@ -144,10 +145,10 @@ module ActsAsTaggableOn::Taggable
|
|
144
145
|
|
145
146
|
## Generate scope:
|
146
147
|
tagging_scope = ActsAsTaggableOn::Tagging.select("#{ActsAsTaggableOn::Tagging.table_name}.tag_id, COUNT(#{ActsAsTaggableOn::Tagging.table_name}.tag_id) AS tags_count")
|
147
|
-
tag_scope = ActsAsTaggableOn::Tag.select("#{ActsAsTaggableOn::Tag.table_name}.*, #{ActsAsTaggableOn::Tagging.table_name}.tags_count AS count").order(options[:order]).limit(options[:limit])
|
148
|
+
tag_scope = ActsAsTaggableOn::Tag.select("#{ActsAsTaggableOn::Tag.table_name}.*, #{ActsAsTaggableOn::Tagging.table_name}.tags_count AS count").order(options[:order]).limit(options[:limit])
|
148
149
|
|
149
150
|
# Joins and conditions
|
150
|
-
tagging_joins.each { |join| tagging_scope = tagging_scope.joins(join) }
|
151
|
+
tagging_joins.each { |join| tagging_scope = tagging_scope.joins(join) }
|
151
152
|
tagging_conditions.each { |condition| tagging_scope = tagging_scope.where(condition) }
|
152
153
|
|
153
154
|
tag_joins.each { |join| tag_scope = tag_scope.joins(join) }
|
@@ -156,29 +157,38 @@ module ActsAsTaggableOn::Taggable
|
|
156
157
|
# GROUP BY and HAVING clauses:
|
157
158
|
at_least = sanitize_sql(["COUNT(#{ActsAsTaggableOn::Tagging.table_name}.tag_id) >= ?", options.delete(:at_least)]) if options[:at_least]
|
158
159
|
at_most = sanitize_sql(["COUNT(#{ActsAsTaggableOn::Tagging.table_name}.tag_id) <= ?", options.delete(:at_most)]) if options[:at_most]
|
159
|
-
having = ["COUNT(#{ActsAsTaggableOn::Tagging.table_name}.tag_id) > 0", at_least, at_most].compact.join(' AND ')
|
160
|
+
having = ["COUNT(#{ActsAsTaggableOn::Tagging.table_name}.tag_id) > 0", at_least, at_most].compact.join(' AND ')
|
160
161
|
|
161
162
|
group_columns = "#{ActsAsTaggableOn::Tagging.table_name}.tag_id"
|
162
163
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
res = "NULL" if res.blank?
|
164
|
+
unless options[:id]
|
165
|
+
# Append the current scope to the scope, because we can't use scope(:find) in RoR 3.0 anymore:
|
166
|
+
scoped_select = "#{table_name}.#{primary_key}"
|
167
|
+
tagging_scope = tagging_scope.where("#{ActsAsTaggableOn::Tagging.table_name}.taggable_id IN(#{safe_to_sql(select(scoped_select))})")
|
168
|
+
end
|
169
169
|
|
170
|
-
tagging_scope = tagging_scope.where("#{ActsAsTaggableOn::Tagging.table_name}.taggable_id IN(#{res})")
|
171
170
|
tagging_scope = tagging_scope.group(group_columns).having(having)
|
172
171
|
|
173
|
-
tag_scope = tag_scope.joins("JOIN (#{tagging_scope
|
174
|
-
tag_scope
|
172
|
+
tag_scope = tag_scope.joins("JOIN (#{safe_to_sql(tagging_scope)}) AS #{ActsAsTaggableOn::Tagging.table_name} ON #{ActsAsTaggableOn::Tagging.table_name}.tag_id = #{ActsAsTaggableOn::Tag.table_name}.id")
|
173
|
+
tag_scope.extending(CalculationMethods)
|
174
|
+
end
|
175
|
+
|
176
|
+
def safe_to_sql(relation)
|
177
|
+
connection.respond_to?(:unprepared_statement) ? connection.unprepared_statement{relation.to_sql} : relation.to_sql
|
175
178
|
end
|
176
179
|
end
|
177
|
-
|
180
|
+
|
178
181
|
module InstanceMethods
|
179
182
|
def tag_counts_on(context, options={})
|
180
183
|
self.class.tag_counts_on(context, options.merge(:id => id))
|
181
184
|
end
|
182
185
|
end
|
186
|
+
|
187
|
+
module CalculationMethods
|
188
|
+
def count
|
189
|
+
# https://github.com/rails/rails/commit/da9b5d4a8435b744fcf278fffd6d7f1e36d4a4f2
|
190
|
+
super(:all)
|
191
|
+
end
|
192
|
+
end
|
183
193
|
end
|
184
|
-
end
|
194
|
+
end
|