Skip to content

Commit

Permalink
[Misc] Deprecated TagList.from in favor of TagListParser.parse
Browse files Browse the repository at this point in the history
  • Loading branch information
seuros committed May 24, 2014
1 parent 260ed3e commit 3c9b170
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 118 deletions.
1 change: 1 addition & 0 deletions lib/acts-as-taggable-on.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module ActsAsTaggableOn
autoload :Engine
autoload :Tag
autoload :TagList
autoload :TagListParser
autoload :Taggable
autoload :Tagger
autoload :Tagging
Expand Down
90 changes: 13 additions & 77 deletions lib/acts_as_taggable_on/tag_list.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

require 'active_support/core_ext/module/delegation'

module ActsAsTaggableOn
Expand All @@ -8,82 +9,6 @@ def initialize(*args)
add(*args)
end

class << self
##
# Returns a new TagList using the given tag string.
#
# Example:
# tag_list = ActsAsTaggableOn::TagList.from("One , Two, Three")
# tag_list # ["One", "Two", "Three"]
def from(string)
string = string.join(ActsAsTaggableOn.glue) if string.respond_to?(:join)

new.tap do |tag_list|
string = string.to_s.dup


string.gsub!(double_quote_pattern) {
# Append the matched tag to the tag list
tag_list << Regexp.last_match[2]
# Return the matched delimiter ($3) to replace the matched items
''
}

string.gsub!(single_quote_pattern) {
# Append the matched tag ($2) to the tag list
tag_list << Regexp.last_match[2]
# Return an empty string to replace the matched items
''
}

# split the string by the delimiter
# and add to the tag_list
tag_list.add(string.split(Regexp.new delimiter))
end
end

def delimiter
# Parse the quoted tags
d = ActsAsTaggableOn.delimiter
# Separate multiple delimiters by bitwise operator
d = d.join('|') if d.kind_of?(Array)

d
end

def single_quote_pattern
%r{
( # Tag start delimiter ($1)
\A | # Either string start or
#{delimiter} # a delimiter
)
\s*' # quote (') optionally preceded by whitespace
(.*?) # Tag ($2)
'\s* # quote (') optionally followed by whitespace
(?= # Tag end delimiter (not consumed; is zero-length lookahead)
#{delimiter}\s* | # Either a delimiter optionally followed by whitespace or
\z # string end
)
}x
end

def double_quote_pattern
%r{
( # Tag start delimiter ($1)
\A | # Either string start or
#{delimiter} # a delimiter
)
\s*" # quote (") optionally preceded by whitespace
(.*?) # Tag ($2)
"\s* # quote (") optionally followed by whitespace
(?= # Tag end delimiter (not consumed; is zero-length lookahead)
#{delimiter}\s* | # Either a delimiter optionally followed by whitespace or
\z # string end
)
}x
end

end
##
# Add tags to the tag_list. Duplicate or blank tags will be ignored.
# Use the <tt>:parse</tt> option to add an unparsed tag string.
Expand Down Expand Up @@ -165,12 +90,23 @@ def extract_and_apply_options!(args)
options = args.last.is_a?(Hash) ? args.pop : {}
options.assert_valid_keys :parse

args.map! { |a| self.class.from(a) } if options[:parse]
args.map! { |a| TagListParser.parse(a) } if options[:parse]

args.flatten!
end


## DEPRECATED
def self.from(string)
ActiveRecord::Base.logger.warn <<WARNING
ActsAsTaggableOn::TagList.from is deprecated \
and will be removed from v4.0+, use \
ActsAsTaggableOn::TagListParser.parse instead
WARNING
TagListParser.parse(string)
end


end
end

78 changes: 78 additions & 0 deletions lib/acts_as_taggable_on/tag_list_parser.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
module ActsAsTaggableOn
##
# Returns a new TagList using the given tag string.
#
# Example:
# tag_list = ActsAsTaggableOn::TagListParser.parse("One , Two, Three")
# tag_list # ["One", "Two", "Three"]
module TagListParser
class << self
def parse(string)
string = string.join(ActsAsTaggableOn.glue) if string.respond_to?(:join)
TagList.new.tap do |tag_list|
string = string.to_s.dup


string.gsub!(double_quote_pattern) {
# Append the matched tag to the tag list
tag_list << Regexp.last_match[2]
# Return the matched delimiter ($3) to replace the matched items
''
}

string.gsub!(single_quote_pattern) {
# Append the matched tag ($2) to the tag list
tag_list << Regexp.last_match[2]
# Return an empty string to replace the matched items
''
}

# split the string by the delimiter
# and add to the tag_list
tag_list.add(string.split(Regexp.new delimiter))
end
end


# private
def delimiter
# Parse the quoted tags
d = ActsAsTaggableOn.delimiter
# Separate multiple delimiters by bitwise operator
d = d.join('|') if d.kind_of?(Array)
d
end

# ( # Tag start delimiter ($1)
# \A | # Either string start or
# #{delimiter} # a delimiter
# )
# \s*" # quote (") optionally preceded by whitespace
# (.*?) # Tag ($2)
# "\s* # quote (") optionally followed by whitespace
# (?= # Tag end delimiter (not consumed; is zero-length lookahead)
# #{delimiter}\s* | # Either a delimiter optionally followed by whitespace or
# \z # string end
# )
def double_quote_pattern
/(\A|#{delimiter})\s*"(.*?)"\s*(?=#{delimiter}\s*|\z)/
end

# ( # Tag start delimiter ($1)
# \A | # Either string start or
# #{delimiter} # a delimiter
# )
# \s*' # quote (') optionally preceded by whitespace
# (.*?) # Tag ($2)
# '\s* # quote (') optionally followed by whitespace
# (?= # Tag end delimiter (not consumed; is zero-length lookahead)
# #{delimiter}\s* | d # Either a delimiter optionally followed by whitespace or
# \z # string end
# )
def single_quote_pattern
/(\A|#{delimiter})\s*'(.*?)'\s*(?=#{delimiter}\s*|\z)/
end

end
end
end
2 changes: 1 addition & 1 deletion lib/acts_as_taggable_on/taggable/ownership.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def set_owner_tag_list_on(owner, context, new_list)

cache = cached_owned_tag_list_on(context)

cache[owner] = ActsAsTaggableOn::TagList.from(new_list)
cache[owner] = ActsAsTaggableOn::TagListParser.parse(new_list)
end

def reload(*args)
Expand Down
45 changes: 45 additions & 0 deletions spec/acts_as_taggable_on/tag_list_parser_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
require 'spec_helper'

describe ActsAsTaggableOn::TagListParser do
it '#parse should return empty array if empty array is passed' do
expect(ActsAsTaggableOn::TagListParser.parse([])).to be_empty
end

describe 'Multiple Delimiter' do
before do
@old_delimiter = ActsAsTaggableOn.delimiter
end

after do
ActsAsTaggableOn.delimiter = @old_delimiter
end

it 'should separate tags by delimiters' do
ActsAsTaggableOn.delimiter = [',', ' ', '\|']
tag_list = ActsAsTaggableOn::TagListParser.parse('cool, data|I have')
expect(tag_list.to_s).to eq('cool, data, I, have')
end

it 'should escape quote' do
ActsAsTaggableOn.delimiter = [',', ' ', '\|']
tag_list = ActsAsTaggableOn::TagListParser.parse "'I have'|cool, data"
expect(tag_list.to_s).to eq('"I have", cool, data')

tag_list = ActsAsTaggableOn::TagListParser.parse '"I, have"|cool, data'
expect(tag_list.to_s).to eq('"I, have", cool, data')
end

it 'should work for utf8 delimiter and long delimiter' do
ActsAsTaggableOn.delimiter = [',', '的', '可能是']
tag_list = ActsAsTaggableOn::TagListParser.parse('我的东西可能是不见了,还好有备份')
expect(tag_list.to_s).to eq('我, 东西, 不见了, 还好有备份')
end

it 'should work for multiple quoted tags' do
ActsAsTaggableOn.delimiter = [',']
tag_list = ActsAsTaggableOn::TagListParser.parse('"Ruby Monsters","eat Katzenzungen"')
expect(tag_list.to_s).to eq('Ruby Monsters, eat Katzenzungen')
end
end

end
42 changes: 2 additions & 40 deletions spec/acts_as_taggable_on/tag_list_spec.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# encoding: utf-8

require 'spec_helper'

describe ActsAsTaggableOn::TagList do
Expand All @@ -7,9 +7,7 @@

it { should be_kind_of Array }

it '#from should return empty array if empty array is passed' do
expect(ActsAsTaggableOn::TagList.from([])).to be_empty
end


describe '#add' do
it 'should be able to be add a new tag word' do
Expand Down Expand Up @@ -118,41 +116,5 @@

end

describe 'Multiple Delimiter' do
before do
@old_delimiter = ActsAsTaggableOn.delimiter
end

after do
ActsAsTaggableOn.delimiter = @old_delimiter
end

it 'should separate tags by delimiters' do
ActsAsTaggableOn.delimiter = [',', ' ', '\|']
tag_list = ActsAsTaggableOn::TagList.from 'cool, data|I have'
expect(tag_list.to_s).to eq('cool, data, I, have')
end

it 'should escape quote' do
ActsAsTaggableOn.delimiter = [',', ' ', '\|']
tag_list = ActsAsTaggableOn::TagList.from "'I have'|cool, data"
expect(tag_list.to_s).to eq('"I have", cool, data')

tag_list = ActsAsTaggableOn::TagList.from '"I, have"|cool, data'
expect(tag_list.to_s).to eq('"I, have", cool, data')
end

it 'should work for utf8 delimiter and long delimiter' do
ActsAsTaggableOn.delimiter = [',', '的', '可能是']
tag_list = ActsAsTaggableOn::TagList.from '我的东西可能是不见了,还好有备份'
expect(tag_list.to_s).to eq('我, 东西, 不见了, 还好有备份')
end

it 'should work for multiple quoted tags' do
ActsAsTaggableOn.delimiter = [',']
tag_list = ActsAsTaggableOn::TagList.from '"Ruby Monsters","eat Katzenzungen"'
expect(tag_list.to_s).to eq('Ruby Monsters, eat Katzenzungen')
end
end

end

0 comments on commit 3c9b170

Please sign in to comment.