acts-as-taggable-on 0.0.0 → 1.0.6
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/CHANGELOG +2 -9
- data/README +196 -0
- data/Rakefile +10 -47
- data/VERSION +1 -1
- data/lib/acts-as-taggable-on.rb +6 -30
- data/lib/acts_as_taggable_on/acts_as_taggable_on.rb +313 -28
- data/lib/acts_as_taggable_on/acts_as_tagger.rb +45 -40
- data/lib/acts_as_taggable_on/tag.rb +6 -48
- data/lib/acts_as_taggable_on/tag_list.rb +29 -31
- data/lib/acts_as_taggable_on/tagging.rb +1 -18
- data/lib/acts_as_taggable_on/tags_helper.rb +2 -8
- data/rails/init.rb +6 -1
- data/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb +47 -148
- data/spec/acts_as_taggable_on/acts_as_tagger_spec.rb +4 -46
- data/spec/acts_as_taggable_on/tag_list_spec.rb +0 -29
- data/spec/acts_as_taggable_on/tag_spec.rb +7 -95
- data/spec/acts_as_taggable_on/taggable_spec.rb +48 -178
- data/spec/acts_as_taggable_on/tagger_spec.rb +5 -57
- data/spec/acts_as_taggable_on/tagging_spec.rb +1 -25
- data/spec/schema.rb +2 -12
- data/spec/spec.opts +6 -1
- data/spec/spec_helper.rb +34 -35
- metadata +7 -31
- data/Gemfile +0 -6
- data/README.rdoc +0 -212
- data/lib/acts_as_taggable_on/acts_as_taggable_on/cache.rb +0 -56
- data/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb +0 -97
- data/lib/acts_as_taggable_on/acts_as_taggable_on/core.rb +0 -220
- data/lib/acts_as_taggable_on/acts_as_taggable_on/dirty.rb +0 -29
- data/lib/acts_as_taggable_on/acts_as_taggable_on/ownership.rb +0 -101
- data/lib/acts_as_taggable_on/acts_as_taggable_on/related.rb +0 -64
- data/lib/acts_as_taggable_on/compatibility/Gemfile +0 -6
- data/lib/acts_as_taggable_on/compatibility/active_record_backports.rb +0 -17
- data/lib/generators/acts_as_taggable_on/migration/migration_generator.rb +0 -31
- data/lib/generators/acts_as_taggable_on/migration/templates/active_record/migration.rb +0 -28
- data/spec/acts_as_taggable_on/tags_helper_spec.rb +0 -28
- data/spec/bm.rb +0 -52
- data/spec/models.rb +0 -36
@@ -1,47 +1,52 @@
|
|
1
|
-
module
|
2
|
-
module
|
3
|
-
|
4
|
-
base
|
5
|
-
|
6
|
-
|
7
|
-
module ClassMethods
|
8
|
-
def acts_as_tagger(opts={})
|
9
|
-
has_many :owned_taggings, opts.merge(:as => :tagger, :dependent => :destroy,
|
10
|
-
:include => :tag, :class_name => "Tagging")
|
11
|
-
has_many :owned_tags, :through => :owned_taggings, :source => :tag, :uniq => true
|
12
|
-
|
13
|
-
include ActsAsTaggableOn::Tagger::InstanceMethods
|
14
|
-
extend ActsAsTaggableOn::Tagger::SingletonMethods
|
1
|
+
module ActiveRecord
|
2
|
+
module Acts
|
3
|
+
module Tagger
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
15
6
|
end
|
16
|
-
|
17
|
-
|
18
|
-
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def acts_as_tagger(opts={})
|
10
|
+
has_many :owned_taggings, opts.merge(:as => :tagger, :dependent => :destroy,
|
11
|
+
:include => :tag, :class_name => "Tagging")
|
12
|
+
has_many :owned_tags, :through => :owned_taggings, :source => :tag, :uniq => true
|
13
|
+
include ActiveRecord::Acts::Tagger::InstanceMethods
|
14
|
+
extend ActiveRecord::Acts::Tagger::SingletonMethods
|
15
|
+
end
|
16
|
+
|
17
|
+
def is_tagger?
|
18
|
+
false
|
19
|
+
end
|
19
20
|
end
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
21
|
+
|
22
|
+
module InstanceMethods
|
23
|
+
def self.included(base)
|
24
|
+
end
|
25
|
+
|
26
|
+
def tag(taggable, opts={})
|
27
|
+
opts.reverse_merge!(:force => true)
|
28
|
+
|
29
|
+
return false unless taggable.respond_to?(:is_taggable?) && taggable.is_taggable?
|
30
|
+
raise "You need to specify a tag context using :on" unless opts.has_key?(:on)
|
31
|
+
raise "You need to specify some tags using :with" unless opts.has_key?(:with)
|
32
|
+
raise "No context :#{opts[:on]} defined in #{taggable.class.to_s}" unless
|
33
|
+
( opts[:force] || taggable.tag_types.include?(opts[:on]) )
|
34
|
+
|
35
|
+
taggable.set_tag_list_on(opts[:on].to_s, opts[:with], self)
|
36
|
+
taggable.save
|
37
|
+
end
|
38
|
+
|
39
|
+
def is_tagger?
|
40
|
+
self.class.is_tagger?
|
41
|
+
end
|
38
42
|
end
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
43
|
+
|
44
|
+
module SingletonMethods
|
45
|
+
def is_tagger?
|
46
|
+
true
|
47
|
+
end
|
44
48
|
end
|
49
|
+
|
45
50
|
end
|
46
51
|
end
|
47
52
|
end
|
@@ -1,65 +1,23 @@
|
|
1
1
|
class Tag < ActiveRecord::Base
|
2
|
-
|
2
|
+
has_many :taggings
|
3
3
|
|
4
|
-
attr_accessible :name
|
5
|
-
|
6
|
-
### ASSOCIATIONS:
|
7
|
-
|
8
|
-
has_many :taggings, :dependent => :destroy
|
9
|
-
|
10
|
-
### VALIDATIONS:
|
11
|
-
|
12
4
|
validates_presence_of :name
|
13
5
|
validates_uniqueness_of :name
|
14
|
-
|
15
|
-
### SCOPES:
|
16
|
-
|
17
|
-
def self.named(name)
|
18
|
-
where(["name LIKE ?", name])
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.named_any(list)
|
22
|
-
where(list.map { |tag| sanitize_sql(["name LIKE ?", tag.to_s]) }.join(" OR "))
|
23
|
-
end
|
24
6
|
|
25
|
-
|
26
|
-
where(["name LIKE ?", "%#{name}%"])
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.named_like_any(list)
|
30
|
-
where(list.map { |tag| sanitize_sql(["name LIKE ?", "%#{tag.to_s}%"]) }.join(" OR "))
|
31
|
-
end
|
32
|
-
|
33
|
-
### CLASS METHODS:
|
34
|
-
|
7
|
+
# LIKE is used for cross-database case-insensitivity
|
35
8
|
def self.find_or_create_with_like_by_name(name)
|
36
|
-
|
9
|
+
find(:first, :conditions => ["name LIKE ?", name]) || create(:name => name)
|
37
10
|
end
|
38
|
-
|
39
|
-
def self.find_or_create_all_with_like_by_name(*list)
|
40
|
-
list = [list].flatten
|
41
|
-
|
42
|
-
return [] if list.empty?
|
43
|
-
|
44
|
-
existing_tags = Tag.named_any(list).all
|
45
|
-
new_tag_names = list.reject { |name| existing_tags.any? { |tag| tag.name.downcase == name.downcase } }
|
46
|
-
created_tags = new_tag_names.map { |name| Tag.create(:name => name) }
|
47
|
-
|
48
|
-
existing_tags + created_tags
|
49
|
-
end
|
50
|
-
|
51
|
-
### INSTANCE METHODS:
|
52
|
-
|
11
|
+
|
53
12
|
def ==(object)
|
54
13
|
super || (object.is_a?(Tag) && name == object.name)
|
55
14
|
end
|
56
|
-
|
15
|
+
|
57
16
|
def to_s
|
58
17
|
name
|
59
18
|
end
|
60
|
-
|
19
|
+
|
61
20
|
def count
|
62
21
|
read_attribute(:count).to_i
|
63
22
|
end
|
64
|
-
|
65
23
|
end
|
@@ -1,19 +1,17 @@
|
|
1
1
|
class TagList < Array
|
2
|
-
|
3
2
|
cattr_accessor :delimiter
|
4
|
-
|
5
3
|
self.delimiter = ','
|
6
|
-
|
4
|
+
|
7
5
|
def initialize(*args)
|
8
6
|
add(*args)
|
9
7
|
end
|
10
|
-
|
8
|
+
|
11
9
|
attr_accessor :owner
|
12
|
-
|
10
|
+
|
13
11
|
# Add tags to the tag_list. Duplicate or blank tags will be ignored.
|
14
12
|
#
|
15
13
|
# tag_list.add("Fun", "Happy")
|
16
|
-
#
|
14
|
+
#
|
17
15
|
# Use the <tt>:parse</tt> option to add an unparsed tag string.
|
18
16
|
#
|
19
17
|
# tag_list.add("Fun, Happy", :parse => true)
|
@@ -23,34 +21,33 @@ class TagList < Array
|
|
23
21
|
clean!
|
24
22
|
self
|
25
23
|
end
|
26
|
-
|
24
|
+
|
27
25
|
# Remove specific tags from the tag_list.
|
28
|
-
#
|
26
|
+
#
|
29
27
|
# tag_list.remove("Sad", "Lonely")
|
30
28
|
#
|
31
29
|
# Like #add, the <tt>:parse</tt> option can be used to remove multiple tags in a string.
|
32
|
-
#
|
30
|
+
#
|
33
31
|
# tag_list.remove("Sad, Lonely", :parse => true)
|
34
32
|
def remove(*names)
|
35
33
|
extract_and_apply_options!(names)
|
36
34
|
delete_if { |name| names.include?(name) }
|
37
35
|
self
|
38
36
|
end
|
39
|
-
|
37
|
+
|
40
38
|
# Transform the tag_list into a tag string suitable for edting in a form.
|
41
39
|
# The tags are joined with <tt>TagList.delimiter</tt> and quoted if necessary.
|
42
40
|
#
|
43
41
|
# tag_list = TagList.new("Round", "Square,Cube")
|
44
42
|
# tag_list.to_s # 'Round, "Square,Cube"'
|
45
43
|
def to_s
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
tags.map do |name|
|
44
|
+
clean!
|
45
|
+
|
46
|
+
map do |name|
|
50
47
|
name.include?(delimiter) ? "\"#{name}\"" : name
|
51
48
|
end.join(delimiter.ends_with?(" ") ? delimiter : "#{delimiter} ")
|
52
49
|
end
|
53
|
-
|
50
|
+
|
54
51
|
private
|
55
52
|
# Remove whitespace, duplicates, and blanks.
|
56
53
|
def clean!
|
@@ -58,38 +55,39 @@ class TagList < Array
|
|
58
55
|
map!(&:strip)
|
59
56
|
uniq!
|
60
57
|
end
|
61
|
-
|
58
|
+
|
62
59
|
def extract_and_apply_options!(args)
|
63
60
|
options = args.last.is_a?(Hash) ? args.pop : {}
|
64
61
|
options.assert_valid_keys :parse
|
65
|
-
|
62
|
+
|
66
63
|
if options[:parse]
|
67
64
|
args.map! { |a| self.class.from(a) }
|
68
65
|
end
|
69
|
-
|
66
|
+
|
70
67
|
args.flatten!
|
71
68
|
end
|
72
|
-
|
69
|
+
|
73
70
|
class << self
|
74
|
-
|
75
71
|
# Returns a new TagList using the given tag string.
|
76
|
-
#
|
72
|
+
#
|
77
73
|
# tag_list = TagList.from("One , Two, Three")
|
78
74
|
# tag_list # ["One", "Two", "Three"]
|
79
75
|
def from(string)
|
80
|
-
|
81
|
-
|
82
|
-
new.tap do |tag_list|
|
76
|
+
returning new do |tag_list|
|
83
77
|
string = string.to_s.dup
|
84
|
-
|
78
|
+
|
85
79
|
# Parse the quoted tags
|
86
|
-
string.gsub!(/
|
87
|
-
string.gsub!(/
|
88
|
-
|
80
|
+
string.gsub!(/"(.*?)"\s*#{delimiter}?\s*/) { tag_list << $1; "" }
|
81
|
+
string.gsub!(/'(.*?)'\s*#{delimiter}?\s*/) { tag_list << $1; "" }
|
82
|
+
|
89
83
|
tag_list.add(string.split(delimiter))
|
90
84
|
end
|
91
85
|
end
|
92
|
-
|
86
|
+
|
87
|
+
def from_owner(owner, *tags)
|
88
|
+
returning from(*tags) do |taglist|
|
89
|
+
taglist.owner = owner
|
90
|
+
end
|
91
|
+
end
|
93
92
|
end
|
94
|
-
|
95
|
-
end
|
93
|
+
end
|
@@ -1,23 +1,6 @@
|
|
1
1
|
class Tagging < ActiveRecord::Base #:nodoc:
|
2
|
-
include ActsAsTaggableOn::ActiveRecord::Backports if ActiveRecord::VERSION::MAJOR < 3
|
3
|
-
|
4
|
-
attr_accessible :tag,
|
5
|
-
:tag_id,
|
6
|
-
:context,
|
7
|
-
:taggable,
|
8
|
-
:taggable_type,
|
9
|
-
:taggable_id,
|
10
|
-
:tagger,
|
11
|
-
:tagger_type,
|
12
|
-
:tagger_id
|
13
|
-
|
14
2
|
belongs_to :tag
|
15
3
|
belongs_to :taggable, :polymorphic => true
|
16
|
-
belongs_to :tagger,
|
17
|
-
|
4
|
+
belongs_to :tagger, :polymorphic => true
|
18
5
|
validates_presence_of :context
|
19
|
-
validates_presence_of :tag_id
|
20
|
-
|
21
|
-
validates_uniqueness_of :tag_id, :scope => [ :taggable_type, :taggable_id, :context, :tagger_id, :tagger_type ]
|
22
|
-
|
23
6
|
end
|
@@ -1,17 +1,11 @@
|
|
1
1
|
module TagsHelper
|
2
|
-
|
3
2
|
# See the README for an example using tag_cloud.
|
4
3
|
def tag_cloud(tags, classes)
|
5
|
-
tags = tags.all if tags.respond_to?(:all)
|
6
|
-
|
7
|
-
return [] if tags.empty?
|
8
|
-
|
9
4
|
max_count = tags.sort_by(&:count).last.count.to_f
|
10
|
-
|
5
|
+
|
11
6
|
tags.each do |tag|
|
12
7
|
index = ((tag.count / max_count) * (classes.size - 1)).round
|
13
8
|
yield tag, classes[index]
|
14
9
|
end
|
15
10
|
end
|
16
|
-
|
17
|
-
end
|
11
|
+
end
|
data/rails/init.rb
CHANGED
@@ -1 +1,6 @@
|
|
1
|
-
require 'acts-as-taggable-on'
|
1
|
+
require 'acts-as-taggable-on'
|
2
|
+
|
3
|
+
ActiveRecord::Base.send :include, ActiveRecord::Acts::TaggableOn
|
4
|
+
ActiveRecord::Base.send :include, ActiveRecord::Acts::Tagger
|
5
|
+
|
6
|
+
RAILS_DEFAULT_LOGGER.info "** acts_as_taggable_on: initialized properly."
|
@@ -1,66 +1,59 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../spec_helper'
|
2
2
|
|
3
3
|
describe "Acts As Taggable On" do
|
4
|
-
before(:each) do
|
5
|
-
clean_database!
|
6
|
-
end
|
7
|
-
|
8
4
|
it "should provide a class method 'taggable?' that is false for untaggable models" do
|
9
5
|
UntaggableModel.should_not be_taggable
|
10
6
|
end
|
11
|
-
|
7
|
+
|
12
8
|
describe "Taggable Method Generation" do
|
13
9
|
before(:each) do
|
14
10
|
[TaggableModel, Tag, Tagging, TaggableUser].each(&:delete_all)
|
15
11
|
@taggable = TaggableModel.new(:name => "Bob Jones")
|
16
12
|
end
|
17
|
-
|
13
|
+
|
18
14
|
it "should respond 'true' to taggable?" do
|
19
15
|
@taggable.class.should be_taggable
|
20
16
|
end
|
21
|
-
|
17
|
+
|
22
18
|
it "should create a class attribute for tag types" do
|
23
19
|
@taggable.class.should respond_to(:tag_types)
|
24
20
|
end
|
25
|
-
|
26
|
-
it "should create an instance attribute for tag types" do
|
27
|
-
@taggable.should respond_to(:tag_types)
|
28
|
-
end
|
29
|
-
|
30
|
-
it "should have all tag types" do
|
31
|
-
@taggable.tag_types.should == [:tags, :languages, :skills, :needs, :offerings]
|
32
|
-
end
|
33
|
-
|
21
|
+
|
34
22
|
it "should generate an association for each tag type" do
|
35
23
|
@taggable.should respond_to(:tags, :skills, :languages)
|
36
24
|
end
|
37
|
-
|
25
|
+
|
26
|
+
it "should generate a cached column checker for each tag type" do
|
27
|
+
TaggableModel.should respond_to(:caching_tag_list?, :caching_skill_list?, :caching_language_list?)
|
28
|
+
end
|
29
|
+
|
38
30
|
it "should add tagged_with and tag_counts to singleton" do
|
39
|
-
TaggableModel.should respond_to(:
|
31
|
+
TaggableModel.should respond_to(:find_tagged_with, :tag_counts)
|
40
32
|
end
|
41
|
-
|
33
|
+
|
34
|
+
it "should add saving of tag lists and cached tag lists to the instance" do
|
35
|
+
@taggable.should respond_to(:save_cached_tag_list)
|
36
|
+
@taggable.should respond_to(:save_tags)
|
37
|
+
end
|
38
|
+
|
42
39
|
it "should generate a tag_list accessor/setter for each tag type" do
|
43
40
|
@taggable.should respond_to(:tag_list, :skill_list, :language_list)
|
44
41
|
@taggable.should respond_to(:tag_list=, :skill_list=, :language_list=)
|
45
42
|
end
|
46
|
-
|
47
|
-
it "should generate a tag_list accessor, that includes owned tags, for each tag type" do
|
48
|
-
@taggable.should respond_to(:all_tags_list, :all_skills_list, :all_languages_list)
|
49
|
-
end
|
50
43
|
end
|
51
|
-
|
44
|
+
|
52
45
|
describe "Single Table Inheritance" do
|
53
46
|
before do
|
54
47
|
@taggable = TaggableModel.new(:name => "taggable")
|
55
48
|
@inherited_same = InheritingTaggableModel.new(:name => "inherited same")
|
56
49
|
@inherited_different = AlteredInheritingTaggableModel.new(:name => "inherited different")
|
57
50
|
end
|
58
|
-
|
51
|
+
|
59
52
|
it "should pass on tag contexts to STI-inherited models" do
|
60
53
|
@inherited_same.should respond_to(:tag_list, :skill_list, :language_list)
|
61
54
|
@inherited_different.should respond_to(:tag_list, :skill_list, :language_list)
|
62
55
|
end
|
63
|
-
|
56
|
+
|
64
57
|
it "should have tag contexts added in altered STI models" do
|
65
58
|
@inherited_different.should respond_to(:part_list)
|
66
59
|
end
|
@@ -73,112 +66,70 @@ describe "Acts As Taggable On" do
|
|
73
66
|
found_taggable.save
|
74
67
|
end
|
75
68
|
end
|
76
|
-
|
69
|
+
|
77
70
|
describe "Related Objects" do
|
78
71
|
it "should find related objects based on tag names on context" do
|
79
72
|
taggable1 = TaggableModel.create!(:name => "Taggable 1")
|
80
73
|
taggable2 = TaggableModel.create!(:name => "Taggable 2")
|
81
74
|
taggable3 = TaggableModel.create!(:name => "Taggable 3")
|
82
|
-
|
75
|
+
|
83
76
|
taggable1.tag_list = "one, two"
|
84
77
|
taggable1.save
|
85
|
-
|
78
|
+
|
86
79
|
taggable2.tag_list = "three, four"
|
87
80
|
taggable2.save
|
88
|
-
|
81
|
+
|
89
82
|
taggable3.tag_list = "one, four"
|
90
83
|
taggable3.save
|
91
|
-
|
84
|
+
|
92
85
|
taggable1.find_related_tags.should include(taggable3)
|
93
86
|
taggable1.find_related_tags.should_not include(taggable2)
|
94
87
|
end
|
95
|
-
|
88
|
+
|
96
89
|
it "should find other related objects based on tag names on context" do
|
97
90
|
taggable1 = TaggableModel.create!(:name => "Taggable 1")
|
98
91
|
taggable2 = OtherTaggableModel.create!(:name => "Taggable 2")
|
99
92
|
taggable3 = OtherTaggableModel.create!(:name => "Taggable 3")
|
100
|
-
|
93
|
+
|
101
94
|
taggable1.tag_list = "one, two"
|
102
95
|
taggable1.save
|
103
|
-
|
96
|
+
|
104
97
|
taggable2.tag_list = "three, four"
|
105
98
|
taggable2.save
|
106
|
-
|
99
|
+
|
107
100
|
taggable3.tag_list = "one, four"
|
108
101
|
taggable3.save
|
109
|
-
|
102
|
+
|
110
103
|
taggable1.find_related_tags_for(OtherTaggableModel).should include(taggable3)
|
111
104
|
taggable1.find_related_tags_for(OtherTaggableModel).should_not include(taggable2)
|
112
105
|
end
|
113
|
-
|
106
|
+
|
114
107
|
it "should not include the object itself in the list of related objects" do
|
115
108
|
taggable1 = TaggableModel.create!(:name => "Taggable 1")
|
116
109
|
taggable2 = TaggableModel.create!(:name => "Taggable 2")
|
117
|
-
|
118
|
-
taggable1.tag_list = "one"
|
119
|
-
taggable1.save
|
120
|
-
|
121
|
-
taggable2.tag_list = "one, two"
|
122
|
-
taggable2.save
|
123
|
-
|
124
|
-
taggable1.find_related_tags.should include(taggable2)
|
125
|
-
taggable1.find_related_tags.should_not include(taggable1)
|
126
|
-
end
|
127
|
-
end
|
128
110
|
|
129
|
-
describe "Matching Contexts" do
|
130
|
-
it "should find objects with tags of matching contexts" do
|
131
|
-
taggable1 = TaggableModel.create!(:name => "Taggable 1")
|
132
|
-
taggable2 = TaggableModel.create!(:name => "Taggable 2")
|
133
|
-
taggable3 = TaggableModel.create!(:name => "Taggable 3")
|
134
|
-
|
135
|
-
taggable1.offering_list = "one, two"
|
136
|
-
taggable1.save!
|
137
|
-
|
138
|
-
taggable2.need_list = "one, two"
|
139
|
-
taggable2.save!
|
140
|
-
|
141
|
-
taggable3.offering_list = "one, two"
|
142
|
-
taggable3.save!
|
143
|
-
|
144
|
-
taggable1.find_matching_contexts(:offerings, :needs).should include(taggable2)
|
145
|
-
taggable1.find_matching_contexts(:offerings, :needs).should_not include(taggable3)
|
146
|
-
end
|
147
|
-
|
148
|
-
it "should find other related objects with tags of matching contexts" do
|
149
|
-
taggable1 = TaggableModel.create!(:name => "Taggable 1")
|
150
|
-
taggable2 = OtherTaggableModel.create!(:name => "Taggable 2")
|
151
|
-
taggable3 = OtherTaggableModel.create!(:name => "Taggable 3")
|
152
|
-
|
153
|
-
taggable1.offering_list = "one, two"
|
154
|
-
taggable1.save
|
155
|
-
|
156
|
-
taggable2.need_list = "one, two"
|
157
|
-
taggable2.save
|
158
|
-
|
159
|
-
taggable3.offering_list = "one, two"
|
160
|
-
taggable3.save
|
161
|
-
|
162
|
-
taggable1.find_matching_contexts_for(OtherTaggableModel, :offerings, :needs).should include(taggable2)
|
163
|
-
taggable1.find_matching_contexts_for(OtherTaggableModel, :offerings, :needs).should_not include(taggable3)
|
164
|
-
end
|
165
|
-
|
166
|
-
it "should not include the object itself in the list of related objects" do
|
167
|
-
taggable1 = TaggableModel.create!(:name => "Taggable 1")
|
168
|
-
taggable2 = TaggableModel.create!(:name => "Taggable 2")
|
169
|
-
|
170
111
|
taggable1.tag_list = "one"
|
171
112
|
taggable1.save
|
172
|
-
|
113
|
+
|
173
114
|
taggable2.tag_list = "one, two"
|
174
115
|
taggable2.save
|
175
|
-
|
116
|
+
|
176
117
|
taggable1.find_related_tags.should include(taggable2)
|
177
118
|
taggable1.find_related_tags.should_not include(taggable1)
|
178
119
|
end
|
179
120
|
end
|
180
|
-
|
121
|
+
|
181
122
|
describe 'Tagging Contexts' do
|
123
|
+
before(:all) do
|
124
|
+
class Array
|
125
|
+
def freq
|
126
|
+
k=Hash.new(0)
|
127
|
+
self.each {|e| k[e]+=1}
|
128
|
+
k
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
182
133
|
it 'should eliminate duplicate tagging contexts ' do
|
183
134
|
TaggableModel.acts_as_taggable_on(:skills, :skills)
|
184
135
|
TaggableModel.tag_types.freq[:skills].should_not == 3
|
@@ -205,62 +156,10 @@ describe "Acts As Taggable On" do
|
|
205
156
|
TaggableModel.acts_as_taggable_on([nil])
|
206
157
|
}.should_not raise_error
|
207
158
|
end
|
208
|
-
end
|
209
|
-
|
210
|
-
describe 'Caching' do
|
211
|
-
before(:each) do
|
212
|
-
@taggable = CachedModel.new(:name => "Bob Jones")
|
213
|
-
end
|
214
|
-
|
215
|
-
it "should add saving of tag lists and cached tag lists to the instance" do
|
216
|
-
@taggable.should respond_to(:save_cached_tag_list)
|
217
|
-
@taggable.should respond_to(:save_tags)
|
218
|
-
end
|
219
159
|
|
220
|
-
|
221
|
-
|
222
|
-
end
|
223
|
-
|
224
|
-
it 'should not have cached tags' do
|
225
|
-
@taggable.cached_tag_list.should be_blank
|
226
|
-
end
|
227
|
-
|
228
|
-
it 'should cache tags' do
|
229
|
-
@taggable.update_attributes(:tag_list => 'awesome, epic')
|
230
|
-
@taggable.cached_tag_list.should == 'awesome, epic'
|
231
|
-
end
|
232
|
-
|
233
|
-
it 'should keep the cache' do
|
234
|
-
@taggable.update_attributes(:tag_list => 'awesome, epic')
|
235
|
-
@taggable = CachedModel.find(@taggable)
|
236
|
-
@taggable.save!
|
237
|
-
@taggable.cached_tag_list.should == 'awesome, epic'
|
238
|
-
end
|
239
|
-
|
240
|
-
it 'should update the cache' do
|
241
|
-
@taggable.update_attributes(:tag_list => 'awesome, epic')
|
242
|
-
@taggable.update_attributes(:tag_list => 'awesome')
|
243
|
-
@taggable.cached_tag_list.should == 'awesome'
|
244
|
-
end
|
245
|
-
|
246
|
-
it 'should remove the cache' do
|
247
|
-
@taggable.update_attributes(:tag_list => 'awesome, epic')
|
248
|
-
@taggable.update_attributes(:tag_list => '')
|
249
|
-
@taggable.cached_tag_list.should be_blank
|
250
|
-
end
|
251
|
-
|
252
|
-
it 'should have a tag list' do
|
253
|
-
@taggable.update_attributes(:tag_list => 'awesome, epic')
|
254
|
-
@taggable = CachedModel.find(@taggable.id)
|
255
|
-
@taggable.tag_list.sort.should == %w(awesome epic).sort
|
256
|
-
end
|
257
|
-
|
258
|
-
it 'should keep the tag list' do
|
259
|
-
@taggable.update_attributes(:tag_list => 'awesome, epic')
|
260
|
-
@taggable = CachedModel.find(@taggable.id)
|
261
|
-
@taggable.save!
|
262
|
-
@taggable.tag_list.sort.should == %w(awesome epic).sort
|
160
|
+
after(:all) do
|
161
|
+
class Array; remove_method :freq; end
|
263
162
|
end
|
264
163
|
end
|
265
|
-
|
266
|
-
end
|
164
|
+
|
165
|
+
end
|