acts_as_taggable 2.0.1 → 2.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +9 -0
- data/README +14 -0
- data/lib/taggable.rb +67 -8
- data/test/acts_as_taggable_test.rb +573 -375
- data/test/config.yml +10 -0
- data/test/config.yml.sample +6 -0
- data/test/debug.log +1 -0
- metadata +5 -2
data/CHANGELOG
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
2.0.2
|
2
|
+
Updated README
|
3
|
+
First release with PostgreSQL compatability (Need feedback)
|
4
|
+
FEATURE: added tagged_with_all? tagged_with_any?
|
5
|
+
FEATURE: added :sort_list option to the tags_counts method - allows you to pass a Proc and get back an ordered list
|
6
|
+
FEATURE: Overhauled the Unit Test suite to make it easier to run
|
7
|
+
BUGFIX: Fixed escaping in find_related_tags
|
8
|
+
BUGFIX: Fixed problem with :limit and find_related_tags being off by 1
|
9
|
+
BUGFIX: Fixed table alias in find_related_tagged
|
1
10
|
2.0.1
|
2
11
|
FEATURE: Source code now available via Subversion
|
3
12
|
BUGFIX: Typo fix in find_related_tags
|
data/README
CHANGED
@@ -87,3 +87,17 @@ becomes
|
|
87
87
|
class Photo < ActiveRecord::Base
|
88
88
|
acts_as_taggable :join_table => "tags_photos"
|
89
89
|
end
|
90
|
+
|
91
|
+
== Testing
|
92
|
+
|
93
|
+
I'm currently working on overhauling the testing system. You now can point the plugin at a database of your choosing by copying config.yml.sample to the main directory and pointing it at a database that exists. I'll be working on making it easier to switch between MySQL & PostgreSQL to simplify testing.
|
94
|
+
|
95
|
+
The tests are still pretty weak. If you really want to help the project - submit tests that show how you are actually using the software so I can confirm that new versions don't break anything.
|
96
|
+
|
97
|
+
== Bugs/Patches
|
98
|
+
|
99
|
+
This plugin has a site at http://rubyforge.org/projects/taggable/. Please go there to submit patches or bug reports. This is also the best place to find the latest version of the software.
|
100
|
+
|
101
|
+
== Authors
|
102
|
+
|
103
|
+
Demetrius Nunes <demetriusnunes@ NoSPAM @gmail.com> is the original creator of acts_as_taggable (originally announced http://dema.ruby.com.br/articles/2005/08/27/easy-tagging-with-rails). He has since moved on to bigger and better things, but the project owes its existance to him. Since 2.0.0, acts_as_taggable has been maintained by Dirk Elmendorf (ruby@ NoSPAM @economysizegeek.com).
|
data/lib/taggable.rb
CHANGED
@@ -5,7 +5,7 @@ module ActiveRecord
|
|
5
5
|
module Acts #:nodoc:
|
6
6
|
module Taggable #:nodoc:
|
7
7
|
|
8
|
-
def self.append_features(base)
|
8
|
+
def self.append_features(base) #:nodoc:
|
9
9
|
super
|
10
10
|
base.extend(ClassMethods)
|
11
11
|
end
|
@@ -268,7 +268,11 @@ module ActiveRecord
|
|
268
268
|
sql << tag_names.collect {|tag| sanitize_sql( ["#{t}.#{tn} = ?",tag])}.join(" OR ")
|
269
269
|
sql << ")"
|
270
270
|
sql << " AND #{sanitize_sql(options[:conditions])}" if options[:conditions]
|
271
|
-
|
271
|
+
if postgresql?
|
272
|
+
sql << " GROUP BY #{model_columns_for_sql}"
|
273
|
+
else
|
274
|
+
sql << " GROUP BY #{o}.#{o_pk}"
|
275
|
+
end
|
272
276
|
sql << " HAVING COUNT(#{o}.#{o_pk}) = #{tag_names.length}" if options[:all]
|
273
277
|
sql << " ORDER BY #{options[:order]} " if options[:order]
|
274
278
|
add_limit!(sql, options)
|
@@ -313,6 +317,9 @@ module ActiveRecord
|
|
313
317
|
# WHERE clause of the SQL. Just like in regular +ActiveRecord::Base#find+ methods.
|
314
318
|
#
|
315
319
|
# +:order+: The same as used in +ActiveRecord::Base#find+ methods. By default, this is 'count DESC'.
|
320
|
+
# This should only be used if you want to modify the SQL - to have sorted result be returned use +:sort_list+:
|
321
|
+
#
|
322
|
+
# +:sort_list+: This is a proc that is used to return a sorted list instead of a hash
|
316
323
|
#
|
317
324
|
# +:count+: Adds a HAVING clause to the SQL statement, where you can set conditions for the 'count' column. For example: '> 50'
|
318
325
|
#
|
@@ -324,12 +331,18 @@ module ActiveRecord
|
|
324
331
|
sql = "SELECT #{t}.#{t_pk} AS id, #{t}.#{tn} AS name, COUNT(*) AS count FROM #{jt}, #{o}, #{t} WHERE #{jt}.#{t_fk} = #{t}.#{t_pk}
|
325
332
|
AND #{jt}.#{o_fk} = #{o}.#{o_pk}"
|
326
333
|
sql << " AND #{sanitize_sql(options[:conditions])}" if options[:conditions]
|
327
|
-
|
334
|
+
|
335
|
+
sql << " GROUP BY #{t}.#{t_pk},#{t}.#{tn}"
|
328
336
|
sql << " HAVING count #{options[:count]} " if options[:count]
|
329
337
|
sql << " ORDER BY #{options[:order]} " if options[:order]
|
330
338
|
add_limit!(sql, options)
|
331
339
|
result = connection.select_all(sql)
|
332
|
-
|
340
|
+
if !options[:raw]
|
341
|
+
count = result.inject({}) { |hsh, row| hsh[row["#{tn}"]] = row['count'].to_i; hsh }
|
342
|
+
if options[:sort_list] && options[:sort_list].is_a?(Proc)
|
343
|
+
count = options[:sort_list].call(count.keys.collect{|key| [key,count[key]]})
|
344
|
+
end
|
345
|
+
end
|
333
346
|
|
334
347
|
count || result
|
335
348
|
end
|
@@ -375,7 +388,7 @@ module ActiveRecord
|
|
375
388
|
AND jt2.#{o_fk} != jt.#{o_fk}
|
376
389
|
AND jt2.#{t_fk}=jt.#{t_fk} AND o.#{o_pk} = jt2.#{o_fk}"
|
377
390
|
sql << " AND #{sanitize_sql(options[:conditions])}" if options[:conditions]
|
378
|
-
sql << " GROUP BY
|
391
|
+
sql << " GROUP BY o.#{o_pk}"
|
379
392
|
sql << " ORDER BY count DESC"
|
380
393
|
add_limit!(sql, options)
|
381
394
|
|
@@ -397,11 +410,13 @@ module ActiveRecord
|
|
397
410
|
def find_related_tags(tags, options = {})
|
398
411
|
tag_names = ActiveRecord::Acts::Taggable.split_tag_names(tags, options[:separator], normalizer)
|
399
412
|
o, o_pk, o_fk, t, tn, t_pk, t_fk, jt = set_locals_for_sql
|
413
|
+
options[:limit] += 1 if options[:limit] # Compensates for the counting of the original argument
|
414
|
+
|
400
415
|
|
401
416
|
sql = "SELECT jt.#{o_fk} AS o_id FROM #{jt} jt, #{t} t
|
402
417
|
WHERE jt.#{t_fk} = t.#{t_pk} "
|
403
418
|
sql << " AND ( t.#{tn} IN ("
|
404
|
-
sql << tag_names
|
419
|
+
sql << quote_bound_value(tag_names)
|
405
420
|
sql << "))"
|
406
421
|
sql << "GROUP BY jt.#{o_fk}
|
407
422
|
HAVING COUNT(jt.#{o_fk})=#{tag_names.length}"
|
@@ -412,7 +427,7 @@ module ActiveRecord
|
|
412
427
|
sql = "SELECT t.#{t_pk} AS id, t.#{tn} AS #{tn}, COUNT(jt.#{o_fk}) AS count FROM #{jt} jt, #{t} t
|
413
428
|
WHERE jt.#{o_fk} IN (#{o_ids.join(",")})
|
414
429
|
AND t.#{t_pk} = jt.#{t_fk}
|
415
|
-
GROUP BY jt.#{t_fk}
|
430
|
+
GROUP BY t.#{t_pk},t.#{tn},jt.#{t_fk}
|
416
431
|
ORDER BY count DESC"
|
417
432
|
add_limit!(sql, options)
|
418
433
|
|
@@ -458,6 +473,18 @@ module ActiveRecord
|
|
458
473
|
end
|
459
474
|
|
460
475
|
private
|
476
|
+
def postgresql?
|
477
|
+
ActiveRecord::Base.connection.adapter_name == "PostgreSQL" ? true : false
|
478
|
+
end
|
479
|
+
def mysql?
|
480
|
+
ActiveRecord::Base.connection.adapter_name == "MySQL" ? true : false
|
481
|
+
end
|
482
|
+
def model_columns_for_sql
|
483
|
+
self.column_names.collect {|c| c = "#{table_name}.#{c}"}.join(',')
|
484
|
+
end
|
485
|
+
def tag_model_columns_for_sql
|
486
|
+
tag_model.column_names.collect {|c| c = "#{tag_model.table_name}.#{c}"}.join(',')
|
487
|
+
end
|
461
488
|
def set_locals_for_sql
|
462
489
|
[ table_name, primary_key, taggable_foreign_key,
|
463
490
|
tag_model.table_name, tag_model_name, tag_model.primary_key, tag_foreign_key,
|
@@ -469,7 +496,11 @@ module ActiveRecord
|
|
469
496
|
module InstanceMethods
|
470
497
|
# Handles clearing all associated tags
|
471
498
|
def clear_tags!
|
472
|
-
|
499
|
+
if tags_join_model
|
500
|
+
tag_collection.each {|x| x.destroy}
|
501
|
+
else
|
502
|
+
tag_collection.clear
|
503
|
+
end
|
473
504
|
end
|
474
505
|
# This method removes tags from the target object, by parsing the tags parameter
|
475
506
|
# into Tag object instances and removing them from the tag collection of the object if they exist.
|
@@ -573,6 +604,34 @@ module ActiveRecord
|
|
573
604
|
def tagged_with?(tag_name, reload = false)
|
574
605
|
tag_names(reload).include?(tag_name)
|
575
606
|
end
|
607
|
+
# Checks to see if this object has been tagged with all +tags+ - they can be a string,or list
|
608
|
+
# The +options+ hash has the following parameters:
|
609
|
+
# +:separator+ => defines the separator (String or Regex) used to split
|
610
|
+
# the tags parameter and defaults to ' ' (space and line breaks).
|
611
|
+
# +:reload+ => That forces the tag names to be reloaded first
|
612
|
+
def tagged_with_all?(tags, options = {})
|
613
|
+
options = { :separator => ' ', :reload => false }.merge(options)
|
614
|
+
requested= ActiveRecord::Acts::Taggable.split_tag_names(tags, options[:separator], normalizer)
|
615
|
+
tag_names(options[:reload]) if options[:reload]
|
616
|
+
requested.each {|tag_name|
|
617
|
+
return false if !tag_names.include?(tag_name)
|
618
|
+
}
|
619
|
+
return true
|
620
|
+
end
|
621
|
+
# Checks to see if this object has been tagged with any +tags+ - they can be a string,or list
|
622
|
+
# The +options+ hash has the following parameters:
|
623
|
+
# +:separator+ => defines the separator (String or Regex) used to split
|
624
|
+
# the tags parameter and defaults to ' ' (space and line breaks).
|
625
|
+
# +:reload+ => That forces the tag names to be reloaded first
|
626
|
+
def tagged_with_any?(tags, options = {})
|
627
|
+
options = { :separator => ' ', :reload => false }.merge(options)
|
628
|
+
requested= ActiveRecord::Acts::Taggable.split_tag_names(tags, options[:separator], normalizer)
|
629
|
+
tag_names(options[:reload]) if options[:reload]
|
630
|
+
requested.each {|tag_name|
|
631
|
+
return true if tag_names.include?(tag_name)
|
632
|
+
}
|
633
|
+
return false
|
634
|
+
end
|
576
635
|
|
577
636
|
# Calls +find_related_tagged+ passing +self+ as the +related+ parameter.
|
578
637
|
def tagged_related(options = {})
|
@@ -1,412 +1,610 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
require 'rubygems'
|
2
|
+
require 'yaml'
|
3
|
+
require_gem 'activerecord'
|
4
|
+
|
5
|
+
config = open("config.yml") { |f| YAML.load(f.read)}
|
6
|
+
|
7
|
+
ActiveRecord::Base.establish_connection(config["database"])
|
8
|
+
|
9
|
+
|
10
|
+
#AR_PATH = Gem::GemPathSearcher.new.find("active_record").full_gem_path
|
11
|
+
#$:.unshift("#{AR_PATH}/test")
|
12
|
+
#$:.unshift("#{AR_PATH}/test/connections/native_mysql")
|
4
13
|
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
5
14
|
|
6
|
-
require 'abstract_unit'
|
15
|
+
#require 'abstract_unit'
|
7
16
|
require 'taggable'
|
8
17
|
|
9
18
|
@@tag_table_column_name = :name
|
10
19
|
|
11
20
|
ActiveRecord::Base.connection.drop_table :tags rescue nil
|
12
21
|
ActiveRecord::Base.connection.drop_table :tags_topics rescue nil
|
13
|
-
ActiveRecord::Base.connection.drop_table :
|
14
|
-
ActiveRecord::Base.connection.drop_table :
|
15
|
-
ActiveRecord::Base.connection.drop_table :
|
22
|
+
ActiveRecord::Base.connection.drop_table :topics rescue nil
|
23
|
+
ActiveRecord::Base.connection.drop_table :people rescue nil
|
24
|
+
ActiveRecord::Base.connection.drop_table :tag_people rescue nil
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
ActiveRecord::Base.connection.create_table :topics do |t|
|
29
|
+
t.column :name, :string
|
30
|
+
end
|
16
31
|
|
17
32
|
ActiveRecord::Base.connection.create_table :tags do |t|
|
18
|
-
|
33
|
+
t.column @@tag_table_column_name , :string
|
19
34
|
end
|
20
35
|
|
21
36
|
ActiveRecord::Base.connection.create_table :tags_topics, :id => false do |t|
|
22
|
-
|
23
|
-
|
24
|
-
t.column :created_at, :time
|
37
|
+
t.column :tag_id, :integer
|
38
|
+
t.column :topic_id, :integer
|
25
39
|
end
|
26
40
|
|
27
|
-
ActiveRecord::Base.connection.create_table :
|
28
|
-
|
41
|
+
ActiveRecord::Base.connection.create_table :people do |t|
|
42
|
+
t.column :name, :string
|
43
|
+
t.column :email , :string
|
29
44
|
end
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
45
|
+
ActiveRecord::Base.connection.create_table :tag_people do |t|
|
46
|
+
t.column :tag_id, :integer
|
47
|
+
t.column :person_id, :integer
|
48
|
+
t.column :created_at, :datetime
|
49
|
+
t.column :created_by_id, :integer
|
50
|
+
t.column :position, :integer
|
34
51
|
end
|
35
52
|
|
36
|
-
ActiveRecord::Base
|
37
|
-
t.column :tag_id, :int
|
38
|
-
t.column :post_id, :int
|
39
|
-
t.column :created_at, :time
|
40
|
-
t.column :created_by_id, :int
|
41
|
-
t.column :position, :int
|
53
|
+
class Tag < ActiveRecord::Base
|
42
54
|
end
|
43
|
-
|
44
|
-
class Tag < ActiveRecord::Base; end
|
45
55
|
class Topic < ActiveRecord::Base
|
46
56
|
acts_as_taggable
|
47
57
|
end
|
48
58
|
|
49
|
-
class
|
50
|
-
|
51
|
-
|
52
|
-
acts_as_taggable :collection => :keywords, :tag_class_name => 'Keyword'
|
59
|
+
class TagPerson < ActiveRecord::Base
|
60
|
+
acts_as_list :scope => :person
|
61
|
+
belongs_to :created_by, :class_name => "Person", :foreign_key => 'created_by_id'
|
53
62
|
end
|
54
63
|
|
55
|
-
class
|
56
|
-
|
57
|
-
|
58
|
-
class Post < ActiveRecord::Base
|
59
|
-
acts_as_taggable :join_class_name => 'TagPost'
|
64
|
+
class Person < ActiveRecord::Base
|
65
|
+
acts_as_taggable :join_class_name => 'TagPerson'
|
60
66
|
end
|
61
67
|
|
62
|
-
class TagPost
|
63
|
-
acts_as_list :scope => :post
|
64
|
-
|
65
|
-
def before_save
|
66
|
-
self.created_by_id = rand(3) + 1
|
67
|
-
end
|
68
|
-
end
|
69
68
|
|
70
|
-
class Order < ActiveRecord::Base
|
71
|
-
end
|
72
69
|
|
73
70
|
class ActAsTaggableTest < Test::Unit::TestCase
|
74
|
-
fixtures :topics
|
75
|
-
|
76
|
-
def test_singleton_methods
|
77
|
-
assert !Order.respond_to?(:find_tagged_with)
|
78
|
-
assert Firm.respond_to?(:find_tagged_with)
|
79
|
-
assert Firm.respond_to?(:cloud)
|
80
|
-
assert Post.respond_to?(:find_tagged_with)
|
81
|
-
assert Post.respond_to?(:cloud)
|
82
|
-
assert Topic.respond_to?(:find_tagged_with)
|
83
|
-
assert Topic.respond_to?(:tag_count)
|
84
|
-
assert Topic.respond_to?(:tags_count)
|
85
|
-
assert Topic.respond_to?(:cloud)
|
86
|
-
end
|
87
|
-
|
88
|
-
def test_with_defaults
|
89
|
-
test_tagging(Topic.find(:first), Tag, :tags)
|
90
|
-
end
|
91
|
-
|
92
|
-
def test_with_non_defaults
|
93
|
-
test_tagging(Company.find(:first), Keyword, :keywords)
|
94
|
-
end
|
95
|
-
|
96
|
-
def test_tag_with_new_object
|
97
|
-
topic = Topic.new
|
98
|
-
topic.tag 'brazil rio beach'
|
99
|
-
topic.save
|
100
|
-
end
|
101
|
-
|
102
|
-
def test_tagging_with_join_model
|
103
|
-
Tag.delete_all
|
104
|
-
TagPost.delete_all
|
105
|
-
post = Post.find(:first)
|
106
|
-
tags = %w(brazil rio beach)
|
107
|
-
|
108
|
-
post.tag(tags)
|
109
|
-
tags.each { |tag| assert post.tagged_with?(tag) }
|
110
|
-
|
111
|
-
post.save
|
112
|
-
post.tags.reload
|
113
|
-
tags.each { |tag| assert post.tagged_with?(tag) }
|
114
|
-
|
115
|
-
posts = Post.find_tagged_with(:any => 'brazil sampa moutain')
|
116
|
-
assert_equal posts[0], post
|
117
|
-
|
118
|
-
posts = Post.find_tagged_with(:all => 'brazil beach')
|
119
|
-
assert_equal posts[0], post
|
120
|
-
|
121
|
-
posts = Post.find_tagged_with(:all => 'brazil rich')
|
122
|
-
assert_equal 0, posts.size
|
123
|
-
|
124
|
-
posts = Post.find_tagged_with(:all => 'brazil', :conditions => [ 'tags_posts.position = ?', 1])
|
125
|
-
assert_equal posts[0], post
|
126
|
-
|
127
|
-
posts = Post.find_tagged_with(:all => 'rio', :conditions => [ 'tags_posts.position = ?', 2])
|
128
|
-
assert_equal posts[0], post
|
129
|
-
|
130
|
-
posts = Post.find_tagged_with(:all => 'beach', :conditions => [ 'tags_posts.position = ?', 3])
|
131
|
-
assert_equal posts[0], post
|
132
|
-
end
|
133
|
-
|
134
|
-
def test_tags_count_with_join_model
|
135
|
-
p1 = Post.create(:title => 'test1')
|
136
|
-
p2 = Post.create(:title => 'test2')
|
137
|
-
p3 = Post.create(:title => 'test3')
|
138
|
-
|
139
|
-
p1.tag 'a b c d'
|
140
|
-
p2.tag 'a c e f'
|
141
|
-
p3.tag 'a c f g'
|
142
|
-
|
143
|
-
counts = Post.tags_count :count => '>= 2', :limit => 2
|
144
|
-
assert_equal counts.keys.size, 2
|
145
|
-
counts.each { |tag, count| assert count >= 2 }
|
146
|
-
assert counts.keys.include?('a')
|
147
|
-
assert counts.keys.include?('c')
|
148
|
-
end
|
149
|
-
|
150
|
-
def test_tags_count
|
151
|
-
t1 = Topic.create(:title => 'test1')
|
152
|
-
t2 = Topic.create(:title => 'test2')
|
153
|
-
t3 = Topic.create(:title => 'test3')
|
154
|
-
|
155
|
-
t1.tag 'a b c d'
|
156
|
-
t2.tag 'a c e f'
|
157
|
-
t3.tag 'a c f g'
|
158
|
-
|
159
|
-
count = Topic.tags_count
|
160
|
-
assert_equal 3, count['a']
|
161
|
-
assert_equal 1, count['b']
|
162
|
-
assert_equal 3, count['c']
|
163
|
-
assert_equal 1, count['d']
|
164
|
-
assert_equal 1, count['e']
|
165
|
-
assert_equal 2, count['f']
|
166
|
-
assert_equal 1, count['g']
|
167
|
-
assert_equal nil, count['h']
|
168
|
-
|
169
|
-
count = Topic.tags_count :count => '>= 2'
|
170
|
-
assert_equal 3, count['a']
|
171
|
-
assert_equal nil, count['b']
|
172
|
-
assert_equal 3, count['c']
|
173
|
-
assert_equal nil, count['d']
|
174
|
-
assert_equal nil, count['e']
|
175
|
-
assert_equal 2, count['f']
|
176
|
-
assert_equal nil, count['g']
|
177
|
-
assert_equal nil, count['h']
|
178
|
-
|
179
|
-
t4 = Topic.create(:title => 'test4')
|
180
|
-
t4.tag 'a f'
|
181
|
-
|
182
|
-
count = Topic.tags_count :limit => 3
|
183
|
-
assert_equal 4, count['a']
|
184
|
-
assert_equal nil, count['b']
|
185
|
-
assert_equal 3, count['c']
|
186
|
-
assert_equal nil, count['d']
|
187
|
-
assert_equal nil, count['e']
|
188
|
-
assert_equal 3, count['f']
|
189
|
-
assert_equal nil, count['g']
|
190
|
-
assert_equal nil, count['h']
|
191
|
-
|
192
|
-
raw = Topic.tags_count :raw => true
|
193
|
-
assert_equal 7, raw.size
|
194
|
-
assert_equal Array, raw.class
|
195
|
-
assert_equal 'a', raw.first[@@tag_table_column_name.to_s]
|
196
|
-
assert_equal '4', raw.first['count']
|
197
|
-
assert_not_nil raw.first['id']
|
198
|
-
assert_equal 'g', raw.last[@@tag_table_column_name.to_s]
|
199
|
-
assert_equal '1', raw.last['count']
|
200
|
-
assert_not_nil raw.last['id']
|
201
|
-
end
|
202
|
-
|
203
|
-
def test_find_related_tagged
|
204
|
-
t1, t2, t3, t4, t5, t6 = create_test_topics
|
205
|
-
|
206
|
-
assert_equal [ t4, t2, t3 ], t1.tagged_related(:limit => 3)
|
207
|
-
assert_equal [ t5, t1, t3 ], t2.tagged_related(:limit => 3)
|
208
|
-
assert_equal [ t1, t4, t6 ], t3.tagged_related(:limit => 3)
|
209
|
-
assert_equal [ t1, t3, t6 ], t4.tagged_related(:limit => 3)
|
210
|
-
assert_equal [ t2, t1, t3 ], t5.tagged_related(:limit => 3)
|
211
|
-
assert_equal [ t1, t3, t4 ], t6.tagged_related(:limit => 3)
|
212
|
-
end
|
213
|
-
|
214
|
-
def test_find_related_tags
|
215
|
-
t1, t2, t3, t4, t5, t6 = create_test_topics
|
216
|
-
|
217
|
-
tags = Topic.find_related_tags('rome walking')
|
218
|
-
assert_equal 2, tags['greatview']
|
219
|
-
assert_equal 4, tags['clean']
|
220
|
-
assert_equal 2, tags['mustsee']
|
221
|
-
end
|
222
|
-
|
223
|
-
def test_find_tagged_with_on_subclasses
|
224
|
-
firm = Firm.find(:first)
|
225
|
-
firm.tag 'law'
|
226
|
-
firms = Firm.find_tagged_with :any => 'law'
|
227
|
-
assert_equal firm, firms[0]
|
228
|
-
assert_equal 1, firms.size
|
229
|
-
end
|
230
|
-
|
231
|
-
def test_find_tagged_with_any
|
232
|
-
topic1 = Topic.create(:title => 'test1')
|
233
|
-
topic2 = Topic.create(:title => 'test2')
|
234
|
-
topic3 = Topic.create(:title => 'test3')
|
235
|
-
|
236
|
-
topic1.tag('a b c'); topic1.save
|
237
|
-
topic2.tag('a c e'); topic2.save
|
238
|
-
topic3.tag('c d e'); topic3.save
|
239
|
-
|
240
|
-
topics = Topic.find_tagged_with(:any => 'x y z')
|
241
|
-
assert_equal 0, topics.size
|
242
|
-
|
243
|
-
topics = Topic.find_tagged_with(:any => 'a b c d e x y z')
|
244
|
-
assert_equal 3, topics.size
|
245
|
-
assert topics.include?(topic1)
|
246
|
-
assert topics.include?(topic2)
|
247
|
-
assert topics.include?(topic3)
|
248
|
-
|
249
|
-
topics = Topic.find_tagged_with(:any => 'a z')
|
250
|
-
assert_equal 2, topics.size
|
251
|
-
assert topics.include?(topic1)
|
252
|
-
assert topics.include?(topic2)
|
253
|
-
|
254
|
-
topics = Topic.find_tagged_with(:any => 'b')
|
255
|
-
assert_equal 1, topics.size
|
256
|
-
assert topics.include?(topic1)
|
257
|
-
|
258
|
-
topics = Topic.find_tagged_with(:any => 'c')
|
259
|
-
assert_equal 3, topics.size
|
260
|
-
assert topics.include?(topic1)
|
261
|
-
assert topics.include?(topic2)
|
262
|
-
assert topics.include?(topic3)
|
263
|
-
|
264
|
-
topics = Topic.find_tagged_with(:any => 'd')
|
265
|
-
assert_equal 1, topics.size
|
266
|
-
assert topics.include?(topic3)
|
267
71
|
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
72
|
+
#singleton commands = [:replace_tag, :find_related_tagged, :cloud ]
|
73
|
+
#class_commands = tag_names=, tagged_related,tags
|
74
|
+
def setup
|
75
|
+
Tag.delete_all
|
76
|
+
Topic.delete_all
|
77
|
+
Person.delete_all
|
78
|
+
TagPerson.delete_all
|
79
|
+
@topic= Topic.new(:name => "Plugin")
|
80
|
+
@topic.save
|
81
|
+
@first_person = Person.new(:name => "Mike User", :email => "mike@aol.com")
|
82
|
+
@first_person.save
|
83
|
+
@second_person = Person.new(:name => "Sally User", :email => "sally@aol.com")
|
84
|
+
@second_person.save
|
85
|
+
end
|
86
|
+
def test_simple_find_tagged_with
|
87
|
+
@topic.tag "Rails Ruby"
|
88
|
+
assert_equal [@topic], Topic.find_tagged_with(:any => "Rails")
|
89
|
+
assert_equal [@topic], Topic.find_tagged_with(:all => "Rails Ruby")
|
90
|
+
end
|
91
|
+
def test_join_find_tagged_with
|
92
|
+
@first_person.tag "Employee Manager"
|
93
|
+
assert_equal [@first_person], Person.find_tagged_with(:any => "Employee")
|
94
|
+
assert_equal [@first_person], Person.find_tagged_with(:all => "Employee Manager")
|
95
|
+
end
|
96
|
+
def test_simple_find_related_tags
|
97
|
+
@topic.tag "foo'bar,baz", :separator => "," , :clear =>true
|
98
|
+
result = { "baz" => 1}
|
99
|
+
assert_equal result,Topic.find_related_tags("foo'bar")
|
100
|
+
assert_equal result,Topic.find_related_tags("foo'bar", :limit => 1)
|
101
|
+
end
|
102
|
+
def test_tags_count
|
103
|
+
list = []
|
104
|
+
10.times do |x|
|
105
|
+
topic = Topic.new(:name => "Topic #{x}")
|
106
|
+
topic.save
|
107
|
+
list << topic
|
108
|
+
end
|
109
|
+
tags = []
|
110
|
+
10.times do |x|
|
111
|
+
tags << "Tag #{x}"
|
112
|
+
end
|
113
|
+
10.times do |x|
|
114
|
+
list[x].tag tags
|
115
|
+
tags.pop
|
116
|
+
end
|
117
|
+
result = {"Tag 1"=>9, "Tag 2"=>8, "Tag 3"=>7, "Tag 4"=>6,
|
118
|
+
"Tag 5"=>5, "Tag 6"=>4, "Tag 7"=>3, "Tag 8"=>2,
|
119
|
+
"Tag 9"=>1, "Tag 0"=>10}
|
120
|
+
assert_equal result , Topic.tags_count
|
121
|
+
sorted_by_name = result.keys.collect{|key| [key,result[key]]}.sort{|a,b| a[0] <=> b[0]}
|
122
|
+
sorted_by_count = result.keys.collect{|key| [key,result[key]]}.sort{|a,b| a[1] <=> b[1]}
|
123
|
+
assert_equal sorted_by_name, Topic.tags_count(:sort_list => Proc.new {|list| list.sort{|a,b| a[0] <=> b[0]}})
|
124
|
+
assert_equal sorted_by_count, Topic.tags_count(:sort_list => Proc.new {|list| list.sort{|a,b| a[1] <=> b[1]}})
|
125
|
+
|
126
|
+
assert_equal result , Topic.tag_count
|
127
|
+
assert_equal sorted_by_name, Topic.tag_count(:sort_list => Proc.new {|list| list.sort{|a,b| a[0] <=> b[0]}})
|
128
|
+
assert_equal sorted_by_count, Topic.tag_count(:sort_list => Proc.new {|list| list.sort{|a,b| a[1] <=> b[1]}})
|
129
|
+
end
|
130
|
+
def test_simple_tag
|
131
|
+
assert_equal [],@topic.tags
|
132
|
+
@topic.tag "Rails"
|
133
|
+
assert_equal ["Rails"], @topic.tag_names
|
134
|
+
list = ["Mike","John","Sam"]
|
135
|
+
@topic.tag list, :clear => true
|
136
|
+
assert_equal list, @topic.tag_names
|
137
|
+
@topic.tag "foo'bar,baz", :separator => "," , :clear =>true
|
138
|
+
assert_equal ["foo'bar","baz"] , @topic.tag_names
|
139
|
+
|
140
|
+
@topic.tag_remove "foo'bar"
|
141
|
+
assert_equal ["baz"] , @topic.tag_names
|
310
142
|
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
143
|
+
end
|
144
|
+
def test_join_tag
|
145
|
+
assert_equal [], @first_person.tags
|
146
|
+
@first_person.tag "Employee", :attributes => { :created_by_id => @second_person.id}
|
147
|
+
assert_equal ["Employee"], @first_person.tag_names
|
148
|
+
@topic.tag_remove "Employee"
|
149
|
+
assert_equal [] , @topic.tag_names
|
150
|
+
end
|
151
|
+
def test_join_tag_clear_tags!
|
152
|
+
assert_equal [], @first_person.tags
|
153
|
+
@first_person.tag "Employee", :attributes => { :created_by_id => @second_person.id}
|
154
|
+
assert_equal ["Employee"], @first_person.tag_names
|
155
|
+
@first_person.clear_tags!
|
156
|
+
assert_equal 0 , Topic.count_by_sql("SELECT COUNT(*) FROM tag_people")
|
157
|
+
end
|
158
|
+
def test_simple_clear_tags!
|
159
|
+
assert_equal [],@topic.tags
|
160
|
+
assert_equal 0 , Topic.count_by_sql("SELECT COUNT(*) FROM tags_topics")
|
161
|
+
@topic.tag "Rails"
|
162
|
+
assert_equal 1 , Topic.count_by_sql("SELECT COUNT(*) FROM tags_topics")
|
163
|
+
assert_equal ["Rails"], @topic.tag_names
|
164
|
+
@topic.clear_tags!
|
165
|
+
assert_equal [],@topic.tags
|
166
|
+
assert_equal 0 , Topic.count_by_sql("SELECT COUNT(*) FROM tags_topics")
|
167
|
+
end
|
168
|
+
def test_simple_tagged_with?
|
169
|
+
@topic.tag("Ruby Rails")
|
170
|
+
assert @topic.tagged_with?("Ruby")
|
171
|
+
assert !@topic.tagged_with?("Mike")
|
172
|
+
end
|
173
|
+
def test_simple_tagged_with_all?
|
174
|
+
@topic.tag("Ruby Rails")
|
175
|
+
assert @topic.tagged_with_all?("Ruby")
|
176
|
+
assert @topic.tagged_with_all?("Rails Ruby")
|
177
|
+
end
|
178
|
+
def test_simple_tagged_with_any?
|
179
|
+
@topic.tag("Ruby Rails")
|
180
|
+
assert @topic.tagged_with_any?("Ruby")
|
181
|
+
assert @topic.tagged_with_any?("Rails Ruby")
|
182
|
+
assert @topic.tagged_with_any?("Rails Ruby Mike")
|
183
|
+
assert @topic.tagged_with_any?("Sam Rails Ruby Mike")
|
184
|
+
end
|
185
|
+
def test_join_tagged_with?
|
186
|
+
@first_person.tag("Employee Manager")
|
187
|
+
assert @first_person.tagged_with?("Employee")
|
188
|
+
assert !@first_person.tagged_with?("Mike")
|
189
|
+
end
|
190
|
+
def test_join_tagged_with_all?
|
191
|
+
@first_person.tag("Employee Manager")
|
192
|
+
assert @first_person.tagged_with_all?("Employee")
|
193
|
+
assert @first_person.tagged_with_all?("Manager Employee")
|
194
|
+
end
|
195
|
+
def test_join_tagged_with_any?
|
196
|
+
@first_person.tag("Employee Manager")
|
197
|
+
assert @first_person.tagged_with_any?("Employee")
|
198
|
+
assert @first_person.tagged_with_any?("Manager Employee")
|
199
|
+
assert @first_person.tagged_with_any?("Manager Employee Mike")
|
200
|
+
assert @first_person.tagged_with_any?("Sam Manager Employee Mike")
|
201
|
+
end
|
315
202
|
|
316
|
-
|
317
|
-
t1, t2, t3, t4, t5, t6 = create_test_topics
|
318
|
-
|
319
|
-
tags = Topic.tags_count
|
320
|
-
assert_equal 9, tags.size
|
203
|
+
end
|
321
204
|
|
322
|
-
Topic.cloud(tags, ['1', '2', '3', '4', '5', '6']) do |tag, cat|
|
323
|
-
case tag
|
324
|
-
when 'rome': assert_equal cat, '6'
|
325
|
-
when 'luxury': assert_equal cat, '3'
|
326
|
-
when 'clean': assert_equal cat, '6'
|
327
|
-
when 'mustsee': assert_equal cat, '3'
|
328
|
-
when 'greatview': assert_equal cat, '3'
|
329
|
-
when 'italian': assert_equal cat, '2'
|
330
|
-
when 'spicy': assert_equal cat, '2'
|
331
|
-
when 'goodwine': assert_equal cat, '1'
|
332
|
-
when 'wine': assert_equal cat, '1'
|
333
|
-
else
|
334
|
-
flunk 'Unexpected Tag/Category pair'
|
335
|
-
end
|
336
|
-
end
|
337
|
-
end
|
338
|
-
|
339
|
-
private
|
340
|
-
def test_tagging(tagged_object, tag_model, collection)
|
341
|
-
tag_model.delete_all
|
342
|
-
assert_equal 0, tag_model.count
|
343
|
-
|
344
|
-
tagged_object.tag_names << 'rio brazil'
|
345
|
-
tagged_object.save
|
346
|
-
|
347
|
-
assert_equal 2, tag_model.count
|
348
|
-
assert_equal 2, tagged_object.send(collection).size
|
349
205
|
|
350
|
-
tagged_object.tag_names = 'beach surf'
|
351
|
-
assert_equal 4, tag_model.count
|
352
|
-
assert_equal 2, tagged_object.send(collection).size
|
353
|
-
|
354
|
-
tagged_object.tag_names.concat 'soccer+pele', :separator => '+'
|
355
|
-
assert_equal 6, tag_model.count
|
356
|
-
assert_equal 4, tagged_object.send(collection).size
|
357
|
-
|
358
|
-
tag_model.delete_all
|
359
|
-
assert_equal 0, tag_model.count
|
360
|
-
tagged_object.send(collection).reload
|
361
|
-
|
362
|
-
tagged_object.tag_names = 'dhh'
|
363
|
-
assert_equal 1, tag_model.count
|
364
|
-
assert_equal 1, tagged_object.send(collection).size
|
365
|
-
|
366
|
-
tagged_object.tag 'dhh rails my', :clear => true
|
367
|
-
|
368
|
-
assert_equal 3, tag_model.count
|
369
|
-
assert_equal 3, tagged_object.send(collection).size
|
370
|
-
|
371
|
-
tagged_object.tag 'dhh dhh ruby tags', :clear => true
|
372
|
-
assert_equal 5, tag_model.count
|
373
|
-
assert_equal 3, tagged_object.send(collection).size
|
374
|
-
|
375
|
-
tagged_object.tag 'tagging, hello, ruby', :separator => ','
|
376
|
-
assert_equal 7, tag_model.count
|
377
|
-
assert_equal 5, tagged_object.send(collection).size
|
378
206
|
|
379
|
-
all_tags = %w( dhh rails my ruby tags tagging hello )
|
380
|
-
first_tags = %w( dhh ruby tags tagging hello )
|
381
|
-
|
382
|
-
tagged_object.send(collection).reload
|
383
|
-
assert_equal first_tags, tagged_object.tag_names
|
384
|
-
all_tags.each do |tag_name|
|
385
|
-
tag_record = tag_model.find(:first,:conditions=>["#{@@tag_table_column_name.to_s} = ?",tag_name])
|
386
|
-
assert_not_nil tag_record
|
387
|
-
|
388
|
-
if first_tags.include?(tag_name)
|
389
|
-
assert tagged_object.send(collection).include?(tag_record)
|
390
|
-
assert tagged_object.tagged_with?(tag_name)
|
391
|
-
end
|
392
|
-
end
|
393
|
-
end
|
394
207
|
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
208
|
+
################################
|
209
|
+
########OLD UNIT TEST CODE######
|
210
|
+
################################
|
211
|
+
#ActiveRecord::Base.connection.drop_table :keywords rescue nil
|
212
|
+
#ActiveRecord::Base.connection.drop_table :keywords_companies rescue nil
|
213
|
+
#ActiveRecord::Base.connection.drop_table :tags_posts rescue nil
|
214
|
+
|
215
|
+
#ActiveRecord::Base.connection.create_table :tags do |t|
|
216
|
+
# t.column @@tag_table_column_name , :string
|
217
|
+
#end
|
218
|
+
#
|
219
|
+
#ActiveRecord::Base.connection.create_table :tags_topics, :id => false do |t|
|
220
|
+
# t.column :tag_id, :integer
|
221
|
+
# t.column :topic_id, :integer
|
222
|
+
# t.column :created_at, :datetime
|
223
|
+
#end
|
224
|
+
#
|
225
|
+
#ActiveRecord::Base.connection.create_table :keywords do |t|
|
226
|
+
# t.column :name, :string
|
227
|
+
#end
|
228
|
+
#
|
229
|
+
#ActiveRecord::Base.connection.create_table :keywords_companies, :id => false do |t|
|
230
|
+
# t.column :keyword_id, :integer
|
231
|
+
# t.column :company_id, :integer
|
232
|
+
# acts_as_list :scope => :person
|
233
|
+
#end
|
234
|
+
#
|
235
|
+
#ActiveRecord::Base.connection.create_table :tags_posts do |t|
|
236
|
+
# t.column :tag_id, :integer
|
237
|
+
# t.column :post_id, :integer
|
238
|
+
# t.column :created_at, :datetime
|
239
|
+
# t.column :created_by_id, :integer
|
240
|
+
# t.column :position, :integer
|
241
|
+
#end
|
242
|
+
#
|
243
|
+
#class Tag < ActiveRecord::Base; end
|
244
|
+
#class Topic < ActiveRecord::Base
|
245
|
+
# acts_as_taggable
|
246
|
+
#end
|
247
|
+
#
|
248
|
+
#class Keyword < ActiveRecord::Base; end
|
249
|
+
#
|
250
|
+
#class Company < ActiveRecord::Base
|
251
|
+
# acts_as_taggable :collection => :keywords, :tag_class_name => 'Keyword'
|
252
|
+
#end
|
253
|
+
#
|
254
|
+
#class Firm < Company; end
|
255
|
+
#class Client < Company; end
|
256
|
+
#
|
257
|
+
#class Post < ActiveRecord::Base
|
258
|
+
# acts_as_taggable :join_class_name => 'TagPost'
|
259
|
+
#end
|
260
|
+
#
|
261
|
+
#class TagPost
|
262
|
+
# acts_as_list :scope => :post
|
263
|
+
#
|
264
|
+
# def before_save
|
265
|
+
# self.created_by_id = rand(3) + 1
|
266
|
+
# end
|
267
|
+
#end
|
268
|
+
#
|
269
|
+
#class Order < ActiveRecord::Base
|
270
|
+
#end
|
271
|
+
#
|
272
|
+
#class ActAsTaggableTest < Test::Unit::TestCase
|
273
|
+
#
|
274
|
+
# def test_singleton_methods
|
275
|
+
# assert !Order.respond_to?(:find_tagged_with)
|
276
|
+
# assert Firm.respond_to?(:find_tagged_with)
|
277
|
+
# assert Firm.respond_to?(:cloud)
|
278
|
+
# assert Post.respond_to?(:find_tagged_with)
|
279
|
+
# assert Post.respond_to?(:cloud)
|
280
|
+
# assert Topic.respond_to?(:find_tagged_with)
|
281
|
+
# assert Topic.respond_to?(:tag_count)
|
282
|
+
# assert Topic.respond_to?(:tags_count)
|
283
|
+
# assert Topic.respond_to?(:cloud)
|
284
|
+
# end
|
285
|
+
#
|
286
|
+
# def test_with_defaults
|
287
|
+
# test_tagging(Topic.find(:first), Tag, :tags)
|
288
|
+
# end
|
289
|
+
#
|
290
|
+
# def test_with_non_defaults
|
291
|
+
# test_tagging(Company.find(:first), Keyword, :keywords)
|
292
|
+
# end
|
293
|
+
#
|
294
|
+
# def test_tag_with_new_object
|
295
|
+
# topic = Topic.new
|
296
|
+
# topic.tag 'brazil rio beach'
|
297
|
+
# topic.save
|
298
|
+
# end
|
299
|
+
#
|
300
|
+
# def test_tagging_with_join_model
|
301
|
+
# Tag.delete_all
|
302
|
+
# TagPost.delete_all
|
303
|
+
# post = Post.find(:first)
|
304
|
+
# tags = %w(brazil rio beach)
|
305
|
+
#
|
306
|
+
# post.tag(tags)
|
307
|
+
# tags.each { |tag| assert post.tagged_with?(tag) }
|
308
|
+
#
|
309
|
+
# post.save
|
310
|
+
# post.tags.reload
|
311
|
+
# tags.each { |tag| assert post.tagged_with?(tag) }
|
312
|
+
#
|
313
|
+
# posts = Post.find_tagged_with(:any => 'brazil sampa moutain')
|
314
|
+
# assert_equal posts[0], post
|
315
|
+
#
|
316
|
+
# posts = Post.find_tagged_with(:all => 'brazil beach')
|
317
|
+
# assert_equal posts[0], post
|
318
|
+
#
|
319
|
+
# posts = Post.find_tagged_with(:all => 'brazil rich')
|
320
|
+
# assert_equal 0, posts.size
|
321
|
+
#
|
322
|
+
# posts = Post.find_tagged_with(:all => 'brazil', :conditions => [ 'tags_posts.position = ?', 1])
|
323
|
+
# assert_equal posts[0], post
|
324
|
+
#
|
325
|
+
# posts = Post.find_tagged_with(:all => 'rio', :conditions => [ 'tags_posts.position = ?', 2])
|
326
|
+
# assert_equal posts[0], post
|
327
|
+
#
|
328
|
+
# posts = Post.find_tagged_with(:all => 'beach', :conditions => [ 'tags_posts.position = ?', 3])
|
329
|
+
# assert_equal posts[0], post
|
330
|
+
# end
|
331
|
+
#
|
332
|
+
# def test_tags_count_with_join_model
|
333
|
+
# p1 = Post.create(:title => 'test1')
|
334
|
+
# p2 = Post.create(:title => 'test2')
|
335
|
+
# p3 = Post.create(:title => 'test3')
|
336
|
+
#
|
337
|
+
# p1.tag 'a b c d'
|
338
|
+
# p2.tag 'a c e f'
|
339
|
+
# p3.tag 'a c f g'
|
340
|
+
#
|
341
|
+
# counts = Post.tags_count :count => '>= 2', :limit => 2
|
342
|
+
# assert_equal counts.keys.size, 2
|
343
|
+
# counts.each { |tag, count| assert count >= 2 }
|
344
|
+
# assert counts.keys.include?('a')
|
345
|
+
# assert counts.keys.include?('c')
|
346
|
+
# end
|
347
|
+
#
|
348
|
+
# def test_tags_count
|
349
|
+
# t1 = Topic.create(:title => 'test1')
|
350
|
+
# t2 = Topic.create(:title => 'test2')
|
351
|
+
# t3 = Topic.create(:title => 'test3')
|
352
|
+
#
|
353
|
+
# t1.tag 'a b c d'
|
354
|
+
# t2.tag 'a c e f'
|
355
|
+
# t3.tag 'a c f g'
|
356
|
+
#
|
357
|
+
# count = Topic.tags_count
|
358
|
+
# assert_equal 3, count['a']
|
359
|
+
# assert_equal 1, count['b']
|
360
|
+
# assert_equal 3, count['c']
|
361
|
+
# assert_equal 1, count['d']
|
362
|
+
# assert_equal 1, count['e']
|
363
|
+
# assert_equal 2, count['f']
|
364
|
+
# assert_equal 1, count['g']
|
365
|
+
# assert_equal nil, count['h']
|
366
|
+
#
|
367
|
+
# count = Topic.tags_count :count => '>= 2'
|
368
|
+
# assert_equal 3, count['a']
|
369
|
+
# assert_equal nil, count['b']
|
370
|
+
# assert_equal 3, count['c']
|
371
|
+
# assert_equal nil, count['d']
|
372
|
+
# assert_equal nil, count['e']
|
373
|
+
# assert_equal 2, count['f']
|
374
|
+
# assert_equal nil, count['g']
|
375
|
+
# assert_equal nil, count['h']
|
376
|
+
#
|
377
|
+
# t4 = Topic.create(:title => 'test4')
|
378
|
+
# t4.tag 'a f'
|
379
|
+
#
|
380
|
+
# count = Topic.tags_count :limit => 3
|
381
|
+
# assert_equal 4, count['a']
|
382
|
+
# assert_equal nil, count['b']
|
383
|
+
# assert_equal 3, count['c']
|
384
|
+
# assert_equal nil, count['d']
|
385
|
+
# assert_equal nil, count['e']
|
386
|
+
# assert_equal 3, count['f']
|
387
|
+
# assert_equal nil, count['g']
|
388
|
+
# assert_equal nil, count['h']
|
389
|
+
#
|
390
|
+
# raw = Topic.tags_count :raw => true
|
391
|
+
# assert_equal 7, raw.size
|
392
|
+
# assert_equal Array, raw.class
|
393
|
+
# assert_equal 'a', raw.first[@@tag_table_column_name.to_s]
|
394
|
+
# assert_equal '4', raw.first['count']
|
395
|
+
# assert_not_nil raw.first['id']
|
396
|
+
# assert_equal 'g', raw.last[@@tag_table_column_name.to_s]
|
397
|
+
# assert_equal '1', raw.last['count']
|
398
|
+
# assert_not_nil raw.last['id']
|
399
|
+
# end
|
400
|
+
#
|
401
|
+
# def test_find_related_tagged
|
402
|
+
# t1, t2, t3, t4, t5, t6 = create_test_topics
|
403
|
+
#
|
404
|
+
# assert_equal [ t4, t2, t3 ], t1.tagged_related(:limit => 3)
|
405
|
+
# assert_equal [ t5, t1, t3 ], t2.tagged_related(:limit => 3)
|
406
|
+
# assert_equal [ t1, t4, t6 ], t3.tagged_related(:limit => 3)
|
407
|
+
# assert_equal [ t1, t3, t6 ], t4.tagged_related(:limit => 3)
|
408
|
+
# assert_equal [ t2, t1, t3 ], t5.tagged_related(:limit => 3)
|
409
|
+
# assert_equal [ t1, t3, t4 ], t6.tagged_related(:limit => 3)
|
410
|
+
# end
|
411
|
+
#
|
412
|
+
# def test_find_related_tags
|
413
|
+
# t1, t2, t3, t4, t5, t6 = create_test_topics
|
414
|
+
#
|
415
|
+
# tags = Topic.find_related_tags('rome walking')
|
416
|
+
# assert_equal 2, tags['greatview']
|
417
|
+
# assert_equal 4, tags['clean']
|
418
|
+
# assert_equal 2, tags['mustsee']
|
419
|
+
# end
|
420
|
+
#
|
421
|
+
# def test_find_tagged_with_on_subclasses
|
422
|
+
# firm = Firm.find(:first)
|
423
|
+
# firm.tag 'law'
|
424
|
+
# firms = Firm.find_tagged_with :any => 'law'
|
425
|
+
# assert_equal firm, firms[0]
|
426
|
+
# assert_equal 1, firms.size
|
427
|
+
# end
|
428
|
+
#
|
429
|
+
# def test_find_tagged_with_any
|
430
|
+
# topic1 = Topic.create(:title => 'test1')
|
431
|
+
# topic2 = Topic.create(:title => 'test2')
|
432
|
+
# topic3 = Topic.create(:title => 'test3')
|
433
|
+
#
|
434
|
+
# topic1.tag('a b c'); topic1.save
|
435
|
+
# topic2.tag('a c e'); topic2.save
|
436
|
+
# topic3.tag('c d e'); topic3.save
|
437
|
+
#
|
438
|
+
# topics = Topic.find_tagged_with(:any => 'x y z')
|
439
|
+
# assert_equal 0, topics.size
|
440
|
+
#
|
441
|
+
# topics = Topic.find_tagged_with(:any => 'a b c d e x y z')
|
442
|
+
# assert_equal 3, topics.size
|
443
|
+
# assert topics.include?(topic1)
|
444
|
+
# assert topics.include?(topic2)
|
445
|
+
# assert topics.include?(topic3)
|
446
|
+
#
|
447
|
+
# topics = Topic.find_tagged_with(:any => 'a z')
|
448
|
+
# assert_equal 2, topics.size
|
449
|
+
# assert topics.include?(topic1)
|
450
|
+
# assert topics.include?(topic2)
|
451
|
+
#
|
452
|
+
# topics = Topic.find_tagged_with(:any => 'b')
|
453
|
+
# assert_equal 1, topics.size
|
454
|
+
# assert topics.include?(topic1)
|
455
|
+
#
|
456
|
+
# topics = Topic.find_tagged_with(:any => 'c')
|
457
|
+
# assert_equal 3, topics.size
|
458
|
+
# assert topics.include?(topic1)
|
459
|
+
# assert topics.include?(topic2)
|
460
|
+
# assert topics.include?(topic3)
|
461
|
+
#
|
462
|
+
# topics = Topic.find_tagged_with(:any => 'd')
|
463
|
+
# assert_equal 1, topics.size
|
464
|
+
# assert topics.include?(topic3)
|
465
|
+
#
|
466
|
+
# topics = Topic.find_tagged_with(:any => 'e')
|
467
|
+
# assert_equal 2, topics.size
|
468
|
+
# assert topics.include?(topic2)
|
469
|
+
# assert topics.include?(topic3)
|
470
|
+
# end
|
471
|
+
#
|
472
|
+
# def test_find_tagged_with_all
|
473
|
+
# topic1 = Topic.create(:title => 'test1')
|
474
|
+
# topic2 = Topic.create(:title => 'test2')
|
475
|
+
# topic3 = Topic.create(:title => 'test3')
|
476
|
+
#
|
477
|
+
# topic1.tag('a b c'); topic1.save
|
478
|
+
# topic2.tag('a c e'); topic2.save
|
479
|
+
# topic3.tag('c d e'); topic3.save
|
480
|
+
#
|
481
|
+
# topics = Topic.find_tagged_with(:all => 'a b d')
|
482
|
+
# assert_equal 0, topics.size
|
483
|
+
#
|
484
|
+
# topics = Topic.find_tagged_with(:all => 'a c')
|
485
|
+
# assert_equal 2, topics.size
|
486
|
+
# assert topics.include?(topic1)
|
487
|
+
# assert topics.include?(topic2)
|
488
|
+
#
|
489
|
+
# topics = Topic.find_tagged_with(:all => 'a+c', :separator => '+')
|
490
|
+
# assert_equal 2, topics.size
|
491
|
+
# assert topics.include?(topic1)
|
492
|
+
# assert topics.include?(topic2)
|
493
|
+
#
|
494
|
+
# topics = Topic.find_tagged_with(:all => 'c e')
|
495
|
+
# assert_equal 2, topics.size
|
496
|
+
# assert topics.include?(topic2)
|
497
|
+
# assert topics.include?(topic3)
|
498
|
+
#
|
499
|
+
# topics = Topic.find_tagged_with(:all => 'c')
|
500
|
+
# assert_equal 3, topics.size
|
501
|
+
# assert topics.include?(topic1)
|
502
|
+
# assert topics.include?(topic2)
|
503
|
+
# assert topics.include?(topic3)
|
504
|
+
#
|
505
|
+
# topics = Topic.find_tagged_with(:all => 'a b c')
|
506
|
+
# assert_equal 1, topics.size
|
507
|
+
# assert topics.include?(topic1)
|
508
|
+
#
|
509
|
+
# topics = Topic.find_tagged_with(:all => 'a c e')
|
510
|
+
# assert_equal 1, topics.size
|
511
|
+
# assert topics.include?(topic2)
|
512
|
+
# end
|
513
|
+
#
|
514
|
+
# def test_tag_cloud
|
515
|
+
# t1, t2, t3, t4, t5, t6 = create_test_topics
|
516
|
+
#
|
517
|
+
# tags = Topic.tags_count
|
518
|
+
# assert_equal 9, tags.size
|
519
|
+
#
|
520
|
+
# Topic.cloud(tags, ['1', '2', '3', '4', '5', '6']) do |tag, cat|
|
521
|
+
# case tag
|
522
|
+
# when 'rome': assert_equal cat, '6'
|
523
|
+
# when 'luxury': assert_equal cat, '3'
|
524
|
+
# when 'clean': assert_equal cat, '6'
|
525
|
+
# when 'mustsee': assert_equal cat, '3'
|
526
|
+
# when 'greatview': assert_equal cat, '3'
|
527
|
+
# when 'italian': assert_equal cat, '2'
|
528
|
+
# when 'spicy': assert_equal cat, '2'
|
529
|
+
# when 'goodwine': assert_equal cat, '1'
|
530
|
+
# when 'wine': assert_equal cat, '1'
|
531
|
+
# else
|
532
|
+
# flunk 'Unexpected Tag/Category pair'
|
533
|
+
# end
|
534
|
+
# end
|
535
|
+
# end
|
536
|
+
#
|
537
|
+
# private
|
538
|
+
# def test_tagging(tagged_object, tag_model, collection)
|
539
|
+
# tag_model.delete_all
|
540
|
+
# assert_equal 0, tag_model.count
|
541
|
+
#
|
542
|
+
# tagged_object.tag_names << 'rio brazil'
|
543
|
+
# tagged_object.save
|
544
|
+
#
|
545
|
+
# assert_equal 2, tag_model.count
|
546
|
+
# assert_equal 2, tagged_object.send(collection).size
|
547
|
+
#
|
548
|
+
# tagged_object.tag_names = 'beach surf'
|
549
|
+
# assert_equal 4, tag_model.count
|
550
|
+
# assert_equal 2, tagged_object.send(collection).size
|
551
|
+
#
|
552
|
+
# tagged_object.tag_names.concat 'soccer+pele', :separator => '+'
|
553
|
+
# assert_equal 6, tag_model.count
|
554
|
+
# assert_equal 4, tagged_object.send(collection).size
|
555
|
+
#
|
556
|
+
# tag_model.delete_all
|
557
|
+
# assert_equal 0, tag_model.count
|
558
|
+
# tagged_object.send(collection).reload
|
559
|
+
#
|
560
|
+
# tagged_object.tag_names = 'dhh'
|
561
|
+
# assert_equal 1, tag_model.count
|
562
|
+
# assert_equal 1, tagged_object.send(collection).size
|
563
|
+
#
|
564
|
+
# tagged_object.tag 'dhh rails my', :clear => true
|
565
|
+
#
|
566
|
+
# assert_equal 3, tag_model.count
|
567
|
+
# assert_equal 3, tagged_object.send(collection).size
|
568
|
+
#
|
569
|
+
# tagged_object.tag 'dhh dhh ruby tags', :clear => true
|
570
|
+
# assert_equal 5, tag_model.count
|
571
|
+
# assert_equal 3, tagged_object.send(collection).size
|
572
|
+
#
|
573
|
+
# tagged_object.tag 'tagging, hello, ruby', :separator => ','
|
574
|
+
# assert_equal 7, tag_model.count
|
575
|
+
# assert_equal 5, tagged_object.send(collection).size
|
576
|
+
#
|
577
|
+
# all_tags = %w( dhh rails my ruby tags tagging hello )
|
578
|
+
# first_tags = %w( dhh ruby tags tagging hello )
|
579
|
+
#
|
580
|
+
# tagged_object.send(collection).reload
|
581
|
+
# assert_equal first_tags, tagged_object.tag_names
|
582
|
+
# all_tags.each do |tag_name|
|
583
|
+
# tag_record = tag_model.find(:first,:conditions=>["#{@@tag_table_column_name.to_s} = ?",tag_name])
|
584
|
+
# assert_not_nil tag_record
|
585
|
+
#
|
586
|
+
# if first_tags.include?(tag_name)
|
587
|
+
# assert tagged_object.send(collection).include?(tag_record)
|
588
|
+
# assert tagged_object.tagged_with?(tag_name)
|
589
|
+
# end
|
590
|
+
# end
|
591
|
+
# end
|
592
|
+
#
|
593
|
+
# def create_test_topics
|
594
|
+
# t1 = Topic.create(:title => 't1')
|
595
|
+
# t2 = Topic.create(:title => 't2')
|
596
|
+
# t3 = Topic.create(:title => 't3')
|
597
|
+
# t4 = Topic.create(:title => 't4')
|
598
|
+
# t5 = Topic.create(:title => 't5')
|
599
|
+
# t6 = Topic.create(:title => 't6')
|
600
|
+
#
|
601
|
+
# t1.tag('rome, luxury, clean, mustsee, greatview', :separator => ','); t1.save
|
602
|
+
# t2.tag('rome, luxury, clean, italian, spicy, goodwine', :separator => ','); t2.save
|
603
|
+
# t3.tag('rome, walking, clean, mustsee', :separator => ','); t3.save
|
604
|
+
# t4.tag('rome, italy, clean, mustsee, greatview', :separator => ','); t4.save
|
605
|
+
# t5.tag('rome, luxury, clean, italian, spicy, wine', :separator => ','); t5.save
|
606
|
+
# t6.tag('rome, walking, clean, greatview', :separator => ','); t6.save
|
607
|
+
#
|
608
|
+
# [ t1, t2, t3, t4, t5, t6 ]
|
609
|
+
# end
|
610
|
+
#end
|
data/test/config.yml
ADDED
data/test/debug.log
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Logfile created on Sun Aug 13 14:26:05 CDT 2006 by logger.rb/1.5.2.7
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: acts_as_taggable
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 2.0.
|
7
|
-
date: 2006-08-
|
6
|
+
version: 2.0.2
|
7
|
+
date: 2006-08-13 00:00:00 -05:00
|
8
8
|
summary: An acts-as Mixin for easy applying and searching tags/folksnomies on Active Record objects
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -29,7 +29,10 @@ authors:
|
|
29
29
|
- Demetrius Nunes,Dirk Elmendorf
|
30
30
|
files:
|
31
31
|
- lib/taggable.rb
|
32
|
+
- test/debug.log
|
32
33
|
- test/acts_as_taggable_test.rb
|
34
|
+
- test/config.yml
|
35
|
+
- test/config.yml.sample
|
33
36
|
- README
|
34
37
|
- CHANGELOG
|
35
38
|
test_files: []
|