acts-as-taggable-on 2.1.1 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.travis.yml +1 -2
- data/README.rdoc +27 -50
- data/acts-as-taggable-on.gemspec +4 -3
- data/lib/acts-as-taggable-on.rb +0 -4
- data/lib/acts-as-taggable-on/version.rb +1 -1
- data/lib/acts_as_taggable_on/acts_as_taggable_on.rb +4 -13
- data/lib/acts_as_taggable_on/acts_as_taggable_on/cache.rb +1 -1
- data/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb +1 -1
- data/lib/acts_as_taggable_on/acts_as_taggable_on/core.rb +29 -17
- data/lib/acts_as_taggable_on/acts_as_taggable_on/related.rb +15 -15
- data/lib/acts_as_taggable_on/tag.rb +12 -13
- data/lib/acts_as_taggable_on/tagging.rb +0 -2
- data/lib/acts_as_taggable_on/utils.rb +7 -8
- data/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb +228 -61
- data/spec/acts_as_taggable_on/tag_list_spec.rb +4 -0
- data/spec/acts_as_taggable_on/tag_spec.rb +11 -15
- data/spec/acts_as_taggable_on/taggable_spec.rb +89 -27
- data/spec/acts_as_taggable_on/tagger_spec.rb +14 -0
- data/spec/acts_as_taggable_on/utils_spec.rb +2 -3
- data/spec/database.yml.sample +1 -1
- data/spec/generators/acts_as_taggable_on/migration/migration_generator_spec.rb +22 -0
- data/spec/models.rb +11 -2
- data/spec/schema.rb +7 -0
- data/spec/spec_helper.rb +1 -0
- metadata +95 -122
- 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/compatibility/Gemfile +0 -8
- data/lib/acts_as_taggable_on/compatibility/active_record_backports.rb +0 -21
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
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,34 +18,15 @@ was used.
|
|
17
18
|
|
18
19
|
=== Rails 2.3.x
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
We are planning no longer to support Rails 2, but if you want to contribute something only for Rails 2, we left rails2 branch for that.
|
23
|
-
|
24
|
-
==== Plugin
|
25
|
-
|
26
|
-
Acts As Taggable On is available both as a gem and as a traditional plugin. For the
|
27
|
-
traditional plugin you can install like so:
|
28
|
-
|
29
|
-
script/plugin install git://github.com/mbleigh/acts-as-taggable-on.git
|
30
|
-
|
31
|
-
Acts As Taggable On is also available as a gem plugin using Rails 2.1's gem dependencies.
|
32
|
-
To install the gem, add this to your config/environment.rb:
|
33
|
-
|
34
|
-
config.gem "acts-as-taggable-on", :source => "http://gemcutter.org", :version => '2.1.0'
|
35
|
-
|
36
|
-
After that, you can run "rake gems:install" to install the gem if you don't already have it.
|
21
|
+
To use it, add it to your Gemfile:
|
37
22
|
|
38
|
-
|
39
|
-
|
40
|
-
1. script/generate acts_as_taggable_on_migration
|
41
|
-
2. rake db:migrate
|
23
|
+
gem 'acts-as-taggable-on', '2.1.0'
|
42
24
|
|
43
25
|
=== Rails 3.x
|
44
26
|
|
45
27
|
To use it, add it to your Gemfile:
|
46
|
-
|
47
|
-
gem 'acts-as-taggable-on'
|
28
|
+
|
29
|
+
gem 'acts-as-taggable-on'
|
48
30
|
|
49
31
|
==== Post Installation
|
50
32
|
|
@@ -87,7 +69,7 @@ compatibility with the will_paginate gem:
|
|
87
69
|
|
88
70
|
class User < ActiveRecord::Base
|
89
71
|
acts_as_taggable_on :tags, :skills
|
90
|
-
|
72
|
+
scope :by_join_date, order("created_at DESC")
|
91
73
|
end
|
92
74
|
|
93
75
|
User.tagged_with("awesome").by_date
|
@@ -95,17 +77,19 @@ compatibility with the will_paginate gem:
|
|
95
77
|
|
96
78
|
# Find a user with matching all tags, not just one
|
97
79
|
User.tagged_with(["awesome", "cool"], :match_all => :true)
|
98
|
-
|
80
|
+
|
99
81
|
# Find a user with any of the tags:
|
100
82
|
User.tagged_with(["awesome", "cool"], :any => true)
|
101
|
-
|
83
|
+
|
102
84
|
# Find a user with any of tags based on context:
|
103
85
|
User.tagged_with(['awesome, cool'], :on => :tags, :any => true).tagged_with(['smart', 'shy'], :on => :skills, :any => true)
|
104
|
-
|
86
|
+
|
87
|
+
Note: User.tagged_with([]) or '' will return [], but not all records.
|
88
|
+
|
105
89
|
=== Relationships
|
106
90
|
|
107
91
|
You can find objects of the same type based on similar tags on certain contexts.
|
108
|
-
Also, objects will be returned in descending order based on the total number of
|
92
|
+
Also, objects will be returned in descending order based on the total number of
|
109
93
|
matched tags.
|
110
94
|
|
111
95
|
@bobby = User.find_by_name("Bobby")
|
@@ -118,8 +102,8 @@ matched tags.
|
|
118
102
|
@tom.skill_list # => ["hacking", "jogging", "diving"]
|
119
103
|
|
120
104
|
@tom.find_related_skills # => [<User name="Bobby">,<User name="Frankie">]
|
121
|
-
@bobby.find_related_skills # => [<User name="Tom">]
|
122
|
-
@frankie.find_related_skills # => [<User name="Tom">]
|
105
|
+
@bobby.find_related_skills # => [<User name="Tom">]
|
106
|
+
@frankie.find_related_skills # => [<User name="Tom">]
|
123
107
|
|
124
108
|
=== Dynamic Tag Contexts
|
125
109
|
|
@@ -149,8 +133,10 @@ Tags can have owners:
|
|
149
133
|
@some_user.tag(@some_photo, :with => "paris, normandy", :on => :locations)
|
150
134
|
@some_user.owned_taggings
|
151
135
|
@some_user.owned_tags
|
152
|
-
@some_photo.locations_from(@some_user)
|
153
|
-
|
136
|
+
@some_photo.locations_from(@some_user) # => ["paris", "normandy"]
|
137
|
+
@some_photo.owner_tags_on(@some_user, :locations) # => [#<ActsAsTaggableOn::Tag id: 1, name: "paris">...]
|
138
|
+
@some_photo.owner_tags_on(nil, :locations) # => Ownerships equivalent to saying @some_photo.locations
|
139
|
+
|
154
140
|
=== Tag cloud calculations
|
155
141
|
|
156
142
|
To construct tag clouds, the frequency of each tag needs to be calculated.
|
@@ -193,23 +179,14 @@ CSS:
|
|
193
179
|
|
194
180
|
== Contributors
|
195
181
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
*
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
=== Patch Contributors
|
206
|
-
|
207
|
-
* tristanzdunn - Related objects of other classes
|
208
|
-
* azabaj - Fixed migrate down
|
209
|
-
* Peter Cooper - named_scope fix
|
210
|
-
* slainer68 - STI fix
|
211
|
-
* harrylove - migration instructions and fix-ups
|
212
|
-
* lawrencepit - cached tag work
|
213
|
-
* sobrinho - fixed tag_cloud helper
|
182
|
+
We have a long list of valued contributors. {Check them all}[https://github.com/mbleigh/acts-as-taggable-on/contributors]
|
183
|
+
|
184
|
+
== Maintainers
|
185
|
+
|
186
|
+
* Artem Kramarenko (artemk)
|
187
|
+
|
188
|
+
== Author
|
189
|
+
|
190
|
+
* Michael Bleigh
|
214
191
|
|
215
192
|
Copyright (c) 2007-2011 Michael Bleigh (http://mbleigh.com/) and Intridea Inc. (http://intridea.com/), released under the MIT license
|
data/acts-as-taggable-on.gemspec
CHANGED
@@ -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{
|
7
|
+
gem.date = %q{2011-12-09}
|
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'
|
13
|
+
gem.add_runtime_dependency 'rails', '~> 3.1'
|
14
14
|
gem.add_development_dependency 'rspec', '~> 2.5'
|
15
|
+
gem.add_development_dependency 'ammeter', '~> 0.1.3'
|
15
16
|
gem.add_development_dependency 'sqlite3'
|
16
|
-
gem.add_development_dependency 'mysql2', '
|
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'
|
data/lib/acts-as-taggable-on.rb
CHANGED
@@ -1,12 +1,9 @@
|
|
1
1
|
require "active_record"
|
2
2
|
require "active_record/version"
|
3
3
|
require "action_view"
|
4
|
-
RAILS_3 = ::ActiveRecord::VERSION::MAJOR >= 3
|
5
4
|
|
6
5
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
7
6
|
|
8
|
-
require "acts_as_taggable_on/compatibility/active_record_backports" unless RAILS_3
|
9
|
-
|
10
7
|
require "acts_as_taggable_on/utils"
|
11
8
|
|
12
9
|
require "acts_as_taggable_on/acts_as_taggable_on"
|
@@ -16,7 +13,6 @@ require "acts_as_taggable_on/acts_as_taggable_on/cache"
|
|
16
13
|
require "acts_as_taggable_on/acts_as_taggable_on/ownership"
|
17
14
|
require "acts_as_taggable_on/acts_as_taggable_on/related"
|
18
15
|
|
19
|
-
#require "acts_as_taggable_on/utils"
|
20
16
|
require "acts_as_taggable_on/acts_as_tagger"
|
21
17
|
require "acts_as_taggable_on/tag"
|
22
18
|
require "acts_as_taggable_on/tag_list"
|
@@ -28,20 +28,11 @@ module ActsAsTaggableOn
|
|
28
28
|
tag_types = tag_types.to_a.flatten.compact.map(&:to_sym)
|
29
29
|
|
30
30
|
if taggable?
|
31
|
-
|
32
|
-
self.tag_types = (self.tag_types + tag_types).uniq
|
33
|
-
else
|
34
|
-
write_inheritable_attribute(:tag_types, (self.tag_types + tag_types).uniq)
|
35
|
-
end
|
31
|
+
self.tag_types = (self.tag_types + tag_types).uniq
|
36
32
|
else
|
37
|
-
if RAILS_3
|
38
33
|
class_attribute :tag_types
|
39
34
|
self.tag_types = tag_types
|
40
|
-
|
41
|
-
write_inheritable_attribute(:tag_types, tag_types)
|
42
|
-
class_inheritable_reader(:tag_types)
|
43
|
-
end
|
44
|
-
|
35
|
+
|
45
36
|
class_eval do
|
46
37
|
has_many :taggings, :as => :taggable, :dependent => :destroy, :include => :tag, :class_name => "ActsAsTaggableOn::Tagging"
|
47
38
|
has_many :base_tags, :through => :taggings, :source => :tag, :class_name => "ActsAsTaggableOn::Tag"
|
@@ -49,8 +40,8 @@ module ActsAsTaggableOn
|
|
49
40
|
def self.taggable?
|
50
41
|
true
|
51
42
|
end
|
52
|
-
|
53
|
-
include ActsAsTaggableOn::Utils
|
43
|
+
|
44
|
+
include ActsAsTaggableOn::Utils
|
54
45
|
include ActsAsTaggableOn::Taggable::Core
|
55
46
|
include ActsAsTaggableOn::Taggable::Collection
|
56
47
|
include ActsAsTaggableOn::Taggable::Cache
|
@@ -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
|
@@ -125,7 +125,7 @@ module ActsAsTaggableOn::Taggable
|
|
125
125
|
tagging_scope = tagging_scope.group(group_by)
|
126
126
|
end
|
127
127
|
|
128
|
-
tag_scope = tag_scope.joins("JOIN (#{tagging_scope.to_sql}) AS
|
128
|
+
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
129
|
tag_scope
|
130
130
|
end
|
131
131
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module ActsAsTaggableOn::Taggable
|
2
|
-
module Core
|
2
|
+
module Core
|
3
3
|
def self.included(base)
|
4
4
|
base.send :include, ActsAsTaggableOn::Taggable::Core::InstanceMethods
|
5
5
|
base.extend ActsAsTaggableOn::Taggable::Core::ClassMethods
|
@@ -8,10 +8,10 @@ module ActsAsTaggableOn::Taggable
|
|
8
8
|
attr_writer :custom_contexts
|
9
9
|
after_save :save_tags
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
base.initialize_acts_as_taggable_on_core
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
module ClassMethods
|
16
16
|
def initialize_acts_as_taggable_on_core
|
17
17
|
tag_types.map(&:to_s).each do |tags_type|
|
@@ -20,9 +20,9 @@ module ActsAsTaggableOn::Taggable
|
|
20
20
|
context_tags = tags_type.to_sym
|
21
21
|
|
22
22
|
class_eval do
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
has_many context_taggings, :as => :taggable, :dependent => :destroy, :include => :tag, :class_name => "ActsAsTaggableOn::Tagging",
|
24
|
+
:conditions => ["#{ActsAsTaggableOn::Tagging.table_name}.context = ?", tags_type]
|
25
|
+
has_many context_tags, :through => context_taggings, :source => :tag, :class_name => "ActsAsTaggableOn::Tag"
|
26
26
|
end
|
27
27
|
|
28
28
|
class_eval %(
|
@@ -38,14 +38,14 @@ module ActsAsTaggableOn::Taggable
|
|
38
38
|
all_tags_list_on('#{tags_type}')
|
39
39
|
end
|
40
40
|
)
|
41
|
-
end
|
41
|
+
end
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
def acts_as_taggable_on(*args)
|
45
45
|
super(*args)
|
46
46
|
initialize_acts_as_taggable_on_core
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
# all column names are necessary for PostgreSQL group clause
|
50
50
|
def grouped_column_names_for(object)
|
51
51
|
object.column_names.map { |column| "#{object.table_name}.#{column}" }.join(", ")
|
@@ -59,12 +59,14 @@ module ActsAsTaggableOn::Taggable
|
|
59
59
|
# * <tt>:exclude</tt> - if set to true, return objects that are *NOT* tagged with the specified tags
|
60
60
|
# * <tt>:any</tt> - if set to true, return objects that are tagged with *ANY* of the specified tags
|
61
61
|
# * <tt>:match_all</tt> - if set to true, return objects that are *ONLY* tagged with the specified tags
|
62
|
+
# * <tt>:owned_by</tt> - return objects that are *ONLY* owned by the owner
|
62
63
|
#
|
63
64
|
# Example:
|
64
65
|
# User.tagged_with("awesome", "cool") # Users that are tagged with awesome and cool
|
65
66
|
# User.tagged_with("awesome", "cool", :exclude => true) # Users that are not tagged with awesome or cool
|
66
67
|
# User.tagged_with("awesome", "cool", :any => true) # Users that are tagged with awesome or cool
|
67
68
|
# User.tagged_with("awesome", "cool", :match_all => true) # Users that are tagged with just awesome and cool
|
69
|
+
# User.tagged_with("awesome", "cool", :owned_by => foo ) # Users that are tagged with just awesome and cool by 'foo'
|
68
70
|
def tagged_with(tags, options = {})
|
69
71
|
tag_list = ActsAsTaggableOn::TagList.from(tags)
|
70
72
|
empty_result = scoped(:conditions => "1 = 0")
|
@@ -75,11 +77,12 @@ module ActsAsTaggableOn::Taggable
|
|
75
77
|
conditions = []
|
76
78
|
|
77
79
|
context = options.delete(:on)
|
80
|
+
owned_by = options.delete(:owned_by)
|
78
81
|
alias_base_name = undecorated_table_name.gsub('.','_')
|
79
82
|
|
80
83
|
if options.delete(:exclude)
|
81
84
|
tags_conditions = tag_list.map { |t| sanitize_sql(["#{ActsAsTaggableOn::Tag.table_name}.name #{like_operator} ?", t]) }.join(" OR ")
|
82
|
-
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}.
|
85
|
+
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)})"
|
83
86
|
|
84
87
|
elsif options.delete(:any)
|
85
88
|
# get tags, drop out if nothing returned (we need at least one)
|
@@ -89,7 +92,7 @@ module ActsAsTaggableOn::Taggable
|
|
89
92
|
# setup taggings alias so we can chain, ex: items_locations_taggings_awesome_cool_123
|
90
93
|
# avoid ambiguous column name
|
91
94
|
taggings_context = context ? "_#{context}" : ''
|
92
|
-
|
95
|
+
|
93
96
|
#TODO: fix alias to be smaller
|
94
97
|
taggings_alias = "#{alias_base_name}#{taggings_context}_taggings_#{tags.map(&:safe_name).join('_')}_#{rand(1024)}"
|
95
98
|
|
@@ -119,6 +122,15 @@ module ActsAsTaggableOn::Taggable
|
|
119
122
|
" AND #{taggings_alias}.tag_id = #{tag.id}"
|
120
123
|
tagging_join << " AND " + sanitize_sql(["#{taggings_alias}.context = ?", context.to_s]) if context
|
121
124
|
|
125
|
+
if owned_by
|
126
|
+
tagging_join << " AND " +
|
127
|
+
sanitize_sql([
|
128
|
+
"#{taggings_alias}.tagger_id = ? AND #{taggings_alias}.tagger_type = ?",
|
129
|
+
owned_by.id,
|
130
|
+
owned_by.class.to_s
|
131
|
+
])
|
132
|
+
end
|
133
|
+
|
122
134
|
joins << tagging_join
|
123
135
|
end
|
124
136
|
end
|
@@ -146,8 +158,8 @@ module ActsAsTaggableOn::Taggable
|
|
146
158
|
def is_taggable?
|
147
159
|
true
|
148
160
|
end
|
149
|
-
end
|
150
|
-
|
161
|
+
end
|
162
|
+
|
151
163
|
module InstanceMethods
|
152
164
|
# all column names are necessary for PostgreSQL group clause
|
153
165
|
def grouped_column_names_for(object)
|
@@ -200,7 +212,7 @@ module ActsAsTaggableOn::Taggable
|
|
200
212
|
|
201
213
|
opts = ["#{tagging_table_name}.context = ?", context.to_s]
|
202
214
|
scope = base_tags.where(opts)
|
203
|
-
|
215
|
+
|
204
216
|
if ActsAsTaggableOn::Tag.using_postgresql?
|
205
217
|
group_columns = grouped_column_names_for(ActsAsTaggableOn::Tag)
|
206
218
|
scope = scope.order("max(#{tagging_table_name}.created_at)").group(group_columns)
|
@@ -233,7 +245,7 @@ module ActsAsTaggableOn::Taggable
|
|
233
245
|
instance_variable_set("@#{context.to_s.singularize}_list", nil)
|
234
246
|
instance_variable_set("@all_#{context.to_s.singularize}_list", nil)
|
235
247
|
end
|
236
|
-
|
248
|
+
|
237
249
|
super(*args)
|
238
250
|
end
|
239
251
|
|
@@ -249,14 +261,14 @@ module ActsAsTaggableOn::Taggable
|
|
249
261
|
current_tags = tags_on(context)
|
250
262
|
old_tags = current_tags - tag_list
|
251
263
|
new_tags = tag_list - current_tags
|
252
|
-
|
264
|
+
|
253
265
|
# Find taggings to remove:
|
254
266
|
old_taggings = taggings.where(:tagger_type => nil, :tagger_id => nil,
|
255
267
|
:context => context.to_s, :tag_id => old_tags).all
|
256
268
|
|
257
269
|
if old_taggings.present?
|
258
270
|
# Destroy old taggings:
|
259
|
-
ActsAsTaggableOn::Tagging.destroy_all
|
271
|
+
ActsAsTaggableOn::Tagging.destroy_all "#{ActsAsTaggableOn::Tagging.primary_key}".to_sym => old_taggings.map(&:id)
|
260
272
|
end
|
261
273
|
|
262
274
|
# Create new taggings:
|
@@ -5,7 +5,7 @@ module ActsAsTaggableOn::Taggable
|
|
5
5
|
base.extend ActsAsTaggableOn::Taggable::Related::ClassMethods
|
6
6
|
base.initialize_acts_as_taggable_on_related
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
module ClassMethods
|
10
10
|
def initialize_acts_as_taggable_on_related
|
11
11
|
tag_types.map(&:to_s).each do |tag_type|
|
@@ -20,7 +20,7 @@ module ActsAsTaggableOn::Taggable
|
|
20
20
|
end
|
21
21
|
)
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
unless tag_types.empty?
|
25
25
|
class_eval %(
|
26
26
|
def find_matching_contexts(search_context, result_context, options = {})
|
@@ -31,43 +31,43 @@ module ActsAsTaggableOn::Taggable
|
|
31
31
|
matching_contexts_for(search_context.to_s, result_context.to_s, klass, options)
|
32
32
|
end
|
33
33
|
)
|
34
|
-
end
|
34
|
+
end
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
def acts_as_taggable_on(*args)
|
38
38
|
super(*args)
|
39
39
|
initialize_acts_as_taggable_on_related
|
40
40
|
end
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
module InstanceMethods
|
44
44
|
def matching_contexts_for(search_context, result_context, klass, options = {})
|
45
45
|
tags_to_find = tags_on(search_context).collect { |t| t.name }
|
46
46
|
|
47
|
-
exclude_self = "#{klass.table_name}.
|
48
|
-
|
47
|
+
exclude_self = "#{klass.table_name}.#{klass.primary_key} != #{id} AND" if [self.class.base_class, self.class].include? klass
|
48
|
+
|
49
49
|
group_columns = ActsAsTaggableOn::Tag.using_postgresql? ? grouped_column_names_for(klass) : "#{klass.table_name}.#{klass.primary_key}"
|
50
|
-
|
51
|
-
klass.scoped({ :select => "#{klass.table_name}.*, COUNT(#{ActsAsTaggableOn::Tag.table_name}.
|
50
|
+
|
51
|
+
klass.scoped({ :select => "#{klass.table_name}.*, COUNT(#{ActsAsTaggableOn::Tag.table_name}.#{ActsAsTaggableOn::Tag.primary_key}) AS count",
|
52
52
|
:from => "#{klass.table_name}, #{ActsAsTaggableOn::Tag.table_name}, #{ActsAsTaggableOn::Tagging.table_name}",
|
53
|
-
:conditions => ["#{exclude_self} #{klass.table_name}.
|
53
|
+
:conditions => ["#{exclude_self} #{klass.table_name}.#{klass.primary_key} = #{ActsAsTaggableOn::Tagging.table_name}.taggable_id AND #{ActsAsTaggableOn::Tagging.table_name}.taggable_type = '#{klass.base_class.to_s}' AND #{ActsAsTaggableOn::Tagging.table_name}.tag_id = #{ActsAsTaggableOn::Tag.table_name}.#{ActsAsTaggableOn::Tag.primary_key} AND #{ActsAsTaggableOn::Tag.table_name}.name IN (?) AND #{ActsAsTaggableOn::Tagging.table_name}.context = ?", tags_to_find, result_context],
|
54
54
|
:group => group_columns,
|
55
55
|
:order => "count DESC" }.update(options))
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
def related_tags_for(context, klass, options = {})
|
59
59
|
tags_to_find = tags_on(context).collect { |t| t.name }
|
60
60
|
|
61
|
-
exclude_self = "#{klass.table_name}.
|
61
|
+
exclude_self = "#{klass.table_name}.#{klass.primary_key} != #{id} AND" if [self.class.base_class, self.class].include? klass
|
62
62
|
|
63
63
|
group_columns = ActsAsTaggableOn::Tag.using_postgresql? ? grouped_column_names_for(klass) : "#{klass.table_name}.#{klass.primary_key}"
|
64
64
|
|
65
|
-
klass.scoped({ :select => "#{klass.table_name}.*, COUNT(#{ActsAsTaggableOn::Tag.table_name}.
|
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}",
|
67
|
-
:conditions => ["#{exclude_self} #{klass.table_name}.
|
67
|
+
:conditions => ["#{exclude_self} #{klass.table_name}.#{klass.primary_key} = #{ActsAsTaggableOn::Tagging.table_name}.taggable_id AND #{ActsAsTaggableOn::Tagging.table_name}.taggable_type = '#{klass.base_class.to_s}' AND #{ActsAsTaggableOn::Tagging.table_name}.tag_id = #{ActsAsTaggableOn::Tag.table_name}.#{ActsAsTaggableOn::Tag.primary_key} AND #{ActsAsTaggableOn::Tag.table_name}.name IN (?)", tags_to_find],
|
68
68
|
:group => group_columns,
|
69
69
|
:order => "count DESC" }.update(options))
|
70
70
|
end
|
71
71
|
end
|
72
72
|
end
|
73
|
-
end
|
73
|
+
end
|