acts-as-taggable-on 2.1.1 → 2.2.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 +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
|