acts-as-taggable-on 2.0.0.rc2 → 2.0.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.
@@ -71,7 +71,9 @@ rake spec:plugins
71
71
  = Usage
72
72
 
73
73
  class User < ActiveRecord::Base
74
- acts_as_taggable_on :tags, :skills, :interests
74
+ # Alias for <tt>acts_as_taggable_on :tags</tt>:
75
+ acts_as_taggable
76
+ acts_as_taggable_on :skills, :interests
75
77
  end
76
78
 
77
79
  @user = User.new(:name => "Bobby")
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.0.0.rc2
1
+ 2.0.0
@@ -4,20 +4,32 @@ module ActsAsTaggableOn
4
4
  false
5
5
  end
6
6
 
7
+ ##
8
+ # This is an alias for calling <tt>acts_as_taggable_on :tags</tt>.
9
+ #
10
+ # Example:
11
+ # class Book < ActiveRecord::Base
12
+ # acts_as_taggable
13
+ # end
7
14
  def acts_as_taggable
8
15
  acts_as_taggable_on :tags
9
16
  end
10
17
 
18
+ ##
19
+ # Make a model taggable on specified contexts.
20
+ #
21
+ # @param [Array] tag_types An array of taggable contexts
22
+ #
23
+ # Example:
24
+ # class User < ActiveRecord::Base
25
+ # acts_as_taggable_on :languages, :skills
26
+ # end
11
27
  def acts_as_taggable_on(*tag_types)
12
28
  tag_types = tag_types.to_a.flatten.compact.map(&:to_sym)
13
29
 
14
30
  if taggable?
15
31
  write_inheritable_attribute(:tag_types, (self.tag_types + tag_types).uniq)
16
32
  else
17
- if ::ActiveRecord::VERSION::MAJOR < 3
18
- include ActsAsTaggableOn::ActiveRecord::Backports
19
- end
20
-
21
33
  write_inheritable_attribute(:tag_types, tag_types)
22
34
  class_inheritable_reader(:tag_types)
23
35
 
@@ -38,17 +38,18 @@ module ActsAsTaggableOn::Taggable
38
38
  all_tag_counts(options.merge({:on => context.to_s}))
39
39
  end
40
40
 
41
+ ##
41
42
  # Calculate the tag counts for all tags.
42
43
  #
43
- # Options:
44
- # :start_at - Restrict the tags to those created after a certain time
45
- # :end_at - Restrict the tags to those created before a certain time
46
- # :conditions - A piece of SQL conditions to add to the query
47
- # :limit - The maximum number of tags to return
48
- # :order - A piece of SQL to order by. Eg 'tags.count desc' or 'taggings.created_at desc'
49
- # :at_least - Exclude tags with a frequency less than the given value
50
- # :at_most - Exclude tags with a frequency greater than the given value
51
- # :on - Scope the find to only include a certain context
44
+ # @param [Hash] options Options:
45
+ # * :start_at - Restrict the tags to those created after a certain time
46
+ # * :end_at - Restrict the tags to those created before a certain time
47
+ # * :conditions - A piece of SQL conditions to add to the query
48
+ # * :limit - The maximum number of tags to return
49
+ # * :order - A piece of SQL to order by. Eg 'tags.count desc' or 'taggings.created_at desc'
50
+ # * :at_least - Exclude tags with a frequency less than the given value
51
+ # * :at_most - Exclude tags with a frequency greater than the given value
52
+ # * :on - Scope the find to only include a certain context
52
53
  def all_tag_counts(options = {})
53
54
  options.assert_valid_keys :start_at, :end_at, :conditions, :at_least, :at_most, :order, :limit, :on, :id
54
55
 
@@ -51,6 +51,20 @@ module ActsAsTaggableOn::Taggable
51
51
  object.column_names.map { |column| "#{object.table_name}.#{column}" }.join(", ")
52
52
  end
53
53
 
54
+ ##
55
+ # Return a scope of objects that are tagged with the specified tags.
56
+ #
57
+ # @param tags The tags that we want to query for
58
+ # @param [Hash] options A hash of options to alter you query:
59
+ # * <tt>:exclude</tt> - if set to true, return objects that are *NOT* tagged with the specified tags
60
+ # * <tt>:any</tt> - if set to true, return objects that are tagged with *ANY* of the specified tags
61
+ # * <tt>:match_all</tt> - if set to true, return objects that are *ONLY* tagged with the specified tags
62
+ #
63
+ # Example:
64
+ # User.tagged_with("awesome", "cool") # Users that are tagged with awesome and cool
65
+ # User.tagged_with("awesome", "cool", :exclude => true) # Users that are not tagged with awesome or cool
66
+ # User.tagged_with("awesome", "cool", :any => true) # Users that are tagged with awesome or cool
67
+ # User.tagged_with("awesome", "cool", :match_all => true) # Users that are tagged with just awesome and cool
54
68
  def tagged_with(tags, options = {})
55
69
  tag_list = TagList.from(tags)
56
70
 
@@ -100,7 +114,10 @@ module ActsAsTaggableOn::Taggable
100
114
  end
101
115
 
102
116
 
103
- joins(joins.join(" ")).group(group).where(conditions.join(" AND ")).readonly(false)
117
+ scoped(:joins => joins.join(" "),
118
+ :group => group,
119
+ :conditions => conditions.join(" AND "),
120
+ :readonly => false)
104
121
  end
105
122
 
106
123
  def is_taggable?
@@ -42,10 +42,10 @@ module ActsAsTaggableOn::Taggable
42
42
  exclude_self = "#{klass.table_name}.id != #{id} AND" if self.class == klass
43
43
 
44
44
  klass.scoped({ :select => "#{klass.table_name}.*, COUNT(#{Tag.table_name}.id) AS count",
45
- :from => "#{klass.table_name}, #{Tag.table_name}, #{Tagging.table_name}",
46
- :conditions => ["#{exclude_self} #{klass.table_name}.id = #{Tagging.table_name}.taggable_id AND #{Tagging.table_name}.taggable_type = '#{klass.to_s}' AND #{Tagging.table_name}.tag_id = #{Tag.table_name}.id AND #{Tag.table_name}.name IN (?) AND #{Tagging.table_name}.context = ?", tags_to_find, result_context],
47
- :group => grouped_column_names_for(klass),
48
- :order => "count DESC" }.update(options))
45
+ :from => "#{klass.table_name}, #{Tag.table_name}, #{Tagging.table_name}",
46
+ :conditions => ["#{exclude_self} #{klass.table_name}.id = #{Tagging.table_name}.taggable_id AND #{Tagging.table_name}.taggable_type = '#{klass.to_s}' AND #{Tagging.table_name}.tag_id = #{Tag.table_name}.id AND #{Tag.table_name}.name IN (?) AND #{Tagging.table_name}.context = ?", tags_to_find, result_context],
47
+ :group => grouped_column_names_for(klass),
48
+ :order => "count DESC" }.update(options))
49
49
  end
50
50
 
51
51
  def related_tags_for(context, klass, options = {})
@@ -54,10 +54,10 @@ module ActsAsTaggableOn::Taggable
54
54
  exclude_self = "#{klass.table_name}.id != #{id} AND" if self.class == klass
55
55
 
56
56
  klass.scoped({ :select => "#{klass.table_name}.*, COUNT(#{Tag.table_name}.id) AS count",
57
- :from => "#{klass.table_name}, #{Tag.table_name}, #{Tagging.table_name}",
58
- :conditions => ["#{exclude_self} #{klass.table_name}.id = #{Tagging.table_name}.taggable_id AND #{Tagging.table_name}.taggable_type = '#{klass.to_s}' AND #{Tagging.table_name}.tag_id = #{Tag.table_name}.id AND #{Tag.table_name}.name IN (?)", tags_to_find],
59
- :group => grouped_column_names_for(klass),
60
- :order => "count DESC" }.update(options))
57
+ :from => "#{klass.table_name}, #{Tag.table_name}, #{Tagging.table_name}",
58
+ :conditions => ["#{exclude_self} #{klass.table_name}.id = #{Tagging.table_name}.taggable_id AND #{Tagging.table_name}.taggable_type = '#{klass.to_s}' AND #{Tagging.table_name}.tag_id = #{Tag.table_name}.id AND #{Tag.table_name}.name IN (?)", tags_to_find],
59
+ :group => grouped_column_names_for(klass),
60
+ :order => "count DESC" }.update(options))
61
61
  end
62
62
  end
63
63
  end
@@ -5,10 +5,20 @@ module ActsAsTaggableOn
5
5
  end
6
6
 
7
7
  module ClassMethods
8
+ ##
9
+ # Make a model a tagger. This allows an instance of a model to claim ownership
10
+ # of tags.
11
+ #
12
+ # Example:
13
+ # class User < ActiveRecord::Base
14
+ # acts_as_tagger
15
+ # end
8
16
  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
17
+ class_eval do
18
+ has_many :owned_taggings, opts.merge(:as => :tagger, :dependent => :destroy,
19
+ :include => :tag, :class_name => "Tagging")
20
+ has_many :owned_tags, :through => :owned_taggings, :source => :tag, :uniq => true
21
+ end
12
22
 
13
23
  include ActsAsTaggableOn::Tagger::InstanceMethods
14
24
  extend ActsAsTaggableOn::Tagger::SingletonMethods
@@ -20,6 +30,16 @@ module ActsAsTaggableOn
20
30
  end
21
31
 
22
32
  module InstanceMethods
33
+ ##
34
+ # Tag a taggable model with tags that are owned by the tagger.
35
+ #
36
+ # @param taggable The object that will be tagged
37
+ # @param [Hash] options An hash with options. Available options are:
38
+ # * <tt>:with</tt> - The tags that you want to
39
+ # * <tt>:on</tt> - The context on which you want to tag
40
+ #
41
+ # Example:
42
+ # @user.tag(@photo, :with => "paris, normandy", :on => :locations)
23
43
  def tag(taggable, opts={})
24
44
  opts.reverse_merge!(:force => true)
25
45
 
@@ -1,21 +1,40 @@
1
1
  class TagList < Array
2
2
 
3
3
  cattr_accessor :delimiter
4
-
5
4
  self.delimiter = ','
6
5
 
6
+ attr_accessor :owner
7
+
7
8
  def initialize(*args)
8
9
  add(*args)
9
10
  end
11
+
12
+ ##
13
+ # Returns a new TagList using the given tag string.
14
+ #
15
+ # Example:
16
+ # tag_list = TagList.from("One , Two, Three")
17
+ # tag_list # ["One", "Two", "Three"]
18
+ def self.from(string)
19
+ string = string.join(", ") if string.respond_to?(:join)
10
20
 
11
- attr_accessor :owner
21
+ new.tap do |tag_list|
22
+ string = string.to_s.dup
23
+
24
+ # Parse the quoted tags
25
+ string.gsub!(/(\A|#{delimiter})\s*"(.*?)"\s*(#{delimiter}\s*|\z)/) { tag_list << $2; $3 }
26
+ string.gsub!(/(\A|#{delimiter})\s*'(.*?)'\s*(#{delimiter}\s*|\z)/) { tag_list << $2; $3 }
12
27
 
28
+ tag_list.add(string.split(delimiter))
29
+ end
30
+ end
31
+
32
+ ##
13
33
  # Add tags to the tag_list. Duplicate or blank tags will be ignored.
14
- #
15
- # tag_list.add("Fun", "Happy")
16
- #
17
34
  # Use the <tt>:parse</tt> option to add an unparsed tag string.
18
35
  #
36
+ # Example:
37
+ # tag_list.add("Fun", "Happy")
19
38
  # tag_list.add("Fun, Happy", :parse => true)
20
39
  def add(*names)
21
40
  extract_and_apply_options!(names)
@@ -24,12 +43,12 @@ class TagList < Array
24
43
  self
25
44
  end
26
45
 
46
+ ##
27
47
  # Remove specific tags from the tag_list.
48
+ # Use the <tt>:parse</tt> option to add an unparsed tag string.
28
49
  #
50
+ # Example:
29
51
  # tag_list.remove("Sad", "Lonely")
30
- #
31
- # Like #add, the <tt>:parse</tt> option can be used to remove multiple tags in a string.
32
- #
33
52
  # tag_list.remove("Sad, Lonely", :parse => true)
34
53
  def remove(*names)
35
54
  extract_and_apply_options!(names)
@@ -37,9 +56,11 @@ class TagList < Array
37
56
  self
38
57
  end
39
58
 
59
+ ##
40
60
  # Transform the tag_list into a tag string suitable for edting in a form.
41
61
  # The tags are joined with <tt>TagList.delimiter</tt> and quoted if necessary.
42
62
  #
63
+ # Example:
43
64
  # tag_list = TagList.new("Round", "Square,Cube")
44
65
  # tag_list.to_s # 'Round, "Square,Cube"'
45
66
  def to_s
@@ -51,7 +72,8 @@ class TagList < Array
51
72
  end.join(delimiter.ends_with?(" ") ? delimiter : "#{delimiter} ")
52
73
  end
53
74
 
54
- private
75
+ private
76
+
55
77
  # Remove whitespace, duplicates, and blanks.
56
78
  def clean!
57
79
  reject!(&:blank?)
@@ -70,26 +92,4 @@ class TagList < Array
70
92
  args.flatten!
71
93
  end
72
94
 
73
- class << self
74
-
75
- # Returns a new TagList using the given tag string.
76
- #
77
- # tag_list = TagList.from("One , Two, Three")
78
- # tag_list # ["One", "Two", "Three"]
79
- def from(string)
80
- string = string.join(", ") if string.respond_to?(:join)
81
-
82
- new.tap do |tag_list|
83
- string = string.to_s.dup
84
-
85
- # Parse the quoted tags
86
- string.gsub!(/(\A|#{delimiter})\s*"(.*?)"\s*(#{delimiter}\s*|\z)/) { tag_list << $2; $3 }
87
- string.gsub!(/(\A|#{delimiter})\s*'(.*?)'\s*(#{delimiter}\s*|\z)/) { tag_list << $2; $3 }
88
-
89
- tag_list.add(string.split(delimiter))
90
- end
91
- end
92
-
93
- end
94
-
95
95
  end
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts-as-taggable-on
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: true
4
+ prerelease: false
5
5
  segments:
6
6
  - 2
7
7
  - 0
8
8
  - 0
9
- - rc2
10
- version: 2.0.0.rc2
9
+ version: 2.0.0
11
10
  platform: ruby
12
11
  authors:
13
12
  - Michael Bleigh
@@ -84,13 +83,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
84
83
  version: "0"
85
84
  required_rubygems_version: !ruby/object:Gem::Requirement
86
85
  requirements:
87
- - - ">"
86
+ - - ">="
88
87
  - !ruby/object:Gem::Version
89
88
  segments:
90
- - 1
91
- - 3
92
- - 1
93
- version: 1.3.1
89
+ - 0
90
+ version: "0"
94
91
  requirements: []
95
92
 
96
93
  rubyforge_project: