require "active_support/core_ext/module/delegation"
module MakeTaggable
class TagList < Array
attr_accessor :owner
attr_accessor :parser
def initialize(*args)
@parser = MakeTaggable.default_parser
add(*args)
end
##
# Add tags to the tag_list. Duplicate or blank tags will be ignored.
# Use the :parse option to add an unparsed tag string.
#
# Example:
# tag_list.add("Fun", "Happy")
# tag_list.add("Fun, Happy", :parse => true)
def add(*names)
extract_and_apply_options!(names)
concat(names)
clean!
self
end
# Append---Add the tag to the tag_list. This
# expression returns the tag_list itself, so several appends
# may be chained together.
def <<(obj)
add(obj)
end
# Concatenation --- Returns a new tag list built by concatenating the
# two tag lists together to produce a third tag list.
def +(other)
TagList.new.add(self).add(other)
end
# Appends the elements of +other_tag_list+ to +self+.
def concat(other_tag_list)
super(other_tag_list).send(:clean!)
self
end
##
# Remove specific tags from the tag_list.
# Use the :parse option to add an unparsed tag string.
#
# Example:
# tag_list.remove("Sad", "Lonely")
# tag_list.remove("Sad, Lonely", :parse => true)
def remove(*names)
extract_and_apply_options!(names)
delete_if { |name| names.include?(name) }
self
end
##
# Transform the tag_list into a tag string suitable for editing in a form.
# The tags are joined with TagList.delimiter and quoted if necessary.
#
# Example:
# tag_list = TagList.new("Round", "Square,Cube")
# tag_list.to_s # 'Round, "Square,Cube"'
def to_s
tags = frozen? ? dup : self
tags.send(:clean!)
tags.map { |name|
d = MakeTaggable.delimiter
d = Regexp.new d.join("|") if d.is_a? Array
name.index(d) ? "\"#{name}\"" : name
}.join(MakeTaggable.glue)
end
private
# Convert everything to string, remove whitespace, duplicates, and blanks.
def clean!
reject!(&:blank?)
map!(&:to_s)
map!(&:strip)
map! { |tag| tag.mb_chars.downcase.to_s } if MakeTaggable.force_lowercase
map!(&:parameterize) if MakeTaggable.force_parameterize
MakeTaggable.strict_case_match ? uniq! : uniq! { |tag| tag.downcase }
self
end
def extract_and_apply_options!(args)
options = args.last.is_a?(Hash) ? args.pop : {}
options.assert_valid_keys :parse, :parser
parser = options[:parser] || @parser
args.map! { |a| parser.new(a).parse } if options[:parse] || options[:parser]
args.flatten!
end
end
end