sb-acts-as-taggable-on 6.5.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.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +39 -0
  5. data/Appraisals +15 -0
  6. data/CHANGELOG.md +330 -0
  7. data/CONTRIBUTING.md +57 -0
  8. data/Gemfile +11 -0
  9. data/Guardfile +5 -0
  10. data/LICENSE.md +20 -0
  11. data/README.md +555 -0
  12. data/Rakefile +21 -0
  13. data/UPGRADING.md +8 -0
  14. data/acts-as-taggable-on.gemspec +32 -0
  15. data/db/migrate/1_acts_as_taggable_on_migration.rb +36 -0
  16. data/db/migrate/2_add_missing_unique_indices.rb +25 -0
  17. data/db/migrate/3_add_taggings_counter_cache_to_tags.rb +19 -0
  18. data/db/migrate/4_add_missing_taggable_index.rb +14 -0
  19. data/db/migrate/5_change_collation_for_tag_names.rb +14 -0
  20. data/db/migrate/6_add_missing_indexes_on_taggings.rb +22 -0
  21. data/gemfiles/activerecord_5.0.gemfile +21 -0
  22. data/gemfiles/activerecord_5.1.gemfile +21 -0
  23. data/gemfiles/activerecord_5.2.gemfile +21 -0
  24. data/gemfiles/activerecord_6.0.gemfile +21 -0
  25. data/lib/acts-as-taggable-on.rb +133 -0
  26. data/lib/acts_as_taggable_on.rb +6 -0
  27. data/lib/acts_as_taggable_on/default_parser.rb +79 -0
  28. data/lib/acts_as_taggable_on/engine.rb +4 -0
  29. data/lib/acts_as_taggable_on/generic_parser.rb +19 -0
  30. data/lib/acts_as_taggable_on/tag.rb +139 -0
  31. data/lib/acts_as_taggable_on/tag_list.rb +106 -0
  32. data/lib/acts_as_taggable_on/taggable.rb +101 -0
  33. data/lib/acts_as_taggable_on/taggable/cache.rb +90 -0
  34. data/lib/acts_as_taggable_on/taggable/collection.rb +183 -0
  35. data/lib/acts_as_taggable_on/taggable/core.rb +322 -0
  36. data/lib/acts_as_taggable_on/taggable/ownership.rb +136 -0
  37. data/lib/acts_as_taggable_on/taggable/related.rb +71 -0
  38. data/lib/acts_as_taggable_on/taggable/tag_list_type.rb +4 -0
  39. data/lib/acts_as_taggable_on/taggable/tagged_with_query.rb +16 -0
  40. data/lib/acts_as_taggable_on/taggable/tagged_with_query/all_tags_query.rb +111 -0
  41. data/lib/acts_as_taggable_on/taggable/tagged_with_query/any_tags_query.rb +70 -0
  42. data/lib/acts_as_taggable_on/taggable/tagged_with_query/exclude_tags_query.rb +82 -0
  43. data/lib/acts_as_taggable_on/taggable/tagged_with_query/query_base.rb +61 -0
  44. data/lib/acts_as_taggable_on/tagger.rb +89 -0
  45. data/lib/acts_as_taggable_on/tagging.rb +36 -0
  46. data/lib/acts_as_taggable_on/tags_helper.rb +15 -0
  47. data/lib/acts_as_taggable_on/utils.rb +37 -0
  48. data/lib/acts_as_taggable_on/version.rb +3 -0
  49. data/lib/tasks/tags_collate_utf8.rake +21 -0
  50. data/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb +285 -0
  51. data/spec/acts_as_taggable_on/acts_as_tagger_spec.rb +112 -0
  52. data/spec/acts_as_taggable_on/caching_spec.rb +129 -0
  53. data/spec/acts_as_taggable_on/default_parser_spec.rb +47 -0
  54. data/spec/acts_as_taggable_on/dirty_spec.rb +142 -0
  55. data/spec/acts_as_taggable_on/generic_parser_spec.rb +14 -0
  56. data/spec/acts_as_taggable_on/related_spec.rb +99 -0
  57. data/spec/acts_as_taggable_on/single_table_inheritance_spec.rb +231 -0
  58. data/spec/acts_as_taggable_on/tag_list_spec.rb +176 -0
  59. data/spec/acts_as_taggable_on/tag_spec.rb +340 -0
  60. data/spec/acts_as_taggable_on/taggable_spec.rb +817 -0
  61. data/spec/acts_as_taggable_on/tagger_spec.rb +153 -0
  62. data/spec/acts_as_taggable_on/tagging_spec.rb +117 -0
  63. data/spec/acts_as_taggable_on/tags_helper_spec.rb +45 -0
  64. data/spec/acts_as_taggable_on/utils_spec.rb +23 -0
  65. data/spec/internal/app/models/altered_inheriting_taggable_model.rb +5 -0
  66. data/spec/internal/app/models/cached_model.rb +3 -0
  67. data/spec/internal/app/models/cached_model_with_array.rb +11 -0
  68. data/spec/internal/app/models/columns_override_model.rb +5 -0
  69. data/spec/internal/app/models/company.rb +15 -0
  70. data/spec/internal/app/models/inheriting_taggable_model.rb +4 -0
  71. data/spec/internal/app/models/market.rb +2 -0
  72. data/spec/internal/app/models/non_standard_id_taggable_model.rb +8 -0
  73. data/spec/internal/app/models/ordered_taggable_model.rb +4 -0
  74. data/spec/internal/app/models/other_cached_model.rb +3 -0
  75. data/spec/internal/app/models/other_taggable_model.rb +4 -0
  76. data/spec/internal/app/models/student.rb +4 -0
  77. data/spec/internal/app/models/taggable_model.rb +14 -0
  78. data/spec/internal/app/models/untaggable_model.rb +3 -0
  79. data/spec/internal/app/models/user.rb +3 -0
  80. data/spec/internal/config/database.yml.sample +19 -0
  81. data/spec/internal/db/schema.rb +110 -0
  82. data/spec/spec_helper.rb +20 -0
  83. data/spec/support/0-helpers.rb +32 -0
  84. data/spec/support/array.rb +9 -0
  85. data/spec/support/database.rb +36 -0
  86. data/spec/support/database_cleaner.rb +21 -0
  87. metadata +269 -0
@@ -0,0 +1,21 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ import "./lib/tasks/tags_collate_utf8.rake"
5
+
6
+ desc 'Default: run specs'
7
+ task default: :spec
8
+
9
+ desc 'Copy sample spec database.yml over if not exists'
10
+ task :copy_db_config do
11
+ cp 'spec/internal/config/database.yml.sample', 'spec/internal/config/database.yml'
12
+ end
13
+
14
+ task spec: [:copy_db_config]
15
+
16
+ require 'rspec/core/rake_task'
17
+ RSpec::Core::RakeTask.new do |t|
18
+ t.pattern = 'spec/**/*_spec.rb'
19
+ end
20
+
21
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,8 @@
1
+ When upgrading
2
+
3
+ Re-run the migrations generator
4
+
5
+ rake acts_as_taggable_on_engine:install:migrations
6
+
7
+ This will create any new migrations and skip existing ones
8
+ Version 3.5.0 has a migration for mysql adapter
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'acts_as_taggable_on/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = 'sb-acts-as-taggable-on'
8
+ gem.version = ActsAsTaggableOn::VERSION
9
+ gem.authors = ['Michael Bleigh', 'Joost Baaij', 'Hernan Velasquez']
10
+ gem.email = %w(michael@intridea.com joost@spacebabies.nl hernamvel@gmail.com)
11
+ gem.description = %q{For SB, with ActsAsTaggableOn, you can tag a single model on several contexts, such as skills, interests, and awards. It also provides other advanced functionality.}
12
+ gem.summary = 'Advanced tagging for Rails.'
13
+ gem.homepage = 'https://github.com/hernamvel/acts-as-taggable-on'
14
+ gem.license = 'MIT'
15
+
16
+ gem.files = `git ls-files`.split($/)
17
+ gem.test_files = gem.files.grep(%r{^spec/})
18
+ gem.require_paths = ['lib']
19
+ gem.required_ruby_version = '>= 2.3.7'
20
+
21
+ if File.exist?('UPGRADING.md')
22
+ gem.post_install_message = File.read('UPGRADING.md')
23
+ end
24
+
25
+ gem.add_runtime_dependency 'activerecord', '>= 5.0', '< 6.1'
26
+
27
+ gem.add_development_dependency 'rspec-rails'
28
+ gem.add_development_dependency 'rspec-its'
29
+ gem.add_development_dependency 'rspec'
30
+ gem.add_development_dependency 'barrier'
31
+ gem.add_development_dependency 'database_cleaner'
32
+ end
@@ -0,0 +1,36 @@
1
+ if ActiveRecord.gem_version >= Gem::Version.new('5.0')
2
+ class ActsAsTaggableOnMigration < ActiveRecord::Migration[4.2]; end
3
+ else
4
+ class ActsAsTaggableOnMigration < ActiveRecord::Migration; end
5
+ end
6
+ ActsAsTaggableOnMigration.class_eval do
7
+ def self.up
8
+ create_table ActsAsTaggableOn.tags_table do |t|
9
+ t.string :name
10
+ t.timestamps
11
+ end
12
+
13
+ create_table ActsAsTaggableOn.taggings_table do |t|
14
+ t.references :tag, foreign_key: { to_table: ActsAsTaggableOn.tags_table }
15
+
16
+ # You should make sure that the column created is
17
+ # long enough to store the required class names.
18
+ t.references :taggable, polymorphic: true
19
+ t.references :tagger, polymorphic: true
20
+
21
+ # Limit is created to prevent MySQL error on index
22
+ # length for MyISAM table type: http://bit.ly/vgW2Ql
23
+ t.string :context, limit: 128
24
+
25
+ t.datetime :created_at
26
+ end
27
+
28
+ add_index ActsAsTaggableOn.taggings_table, :tag_id
29
+ add_index ActsAsTaggableOn.taggings_table, [:taggable_id, :taggable_type, :context], name: 'taggings_taggable_context_idx'
30
+ end
31
+
32
+ def self.down
33
+ drop_table ActsAsTaggableOn.taggings_table
34
+ drop_table ActsAsTaggableOn.tags_table
35
+ end
36
+ end
@@ -0,0 +1,25 @@
1
+ if ActiveRecord.gem_version >= Gem::Version.new('5.0')
2
+ class AddMissingUniqueIndices < ActiveRecord::Migration[4.2]; end
3
+ else
4
+ class AddMissingUniqueIndices < ActiveRecord::Migration; end
5
+ end
6
+ AddMissingUniqueIndices.class_eval do
7
+ def self.up
8
+ add_index ActsAsTaggableOn.tags_table, :name, unique: true
9
+
10
+ remove_index ActsAsTaggableOn.taggings_table, :tag_id if index_exists?(ActsAsTaggableOn.taggings_table, :tag_id)
11
+ remove_index ActsAsTaggableOn.taggings_table, name: 'taggings_taggable_context_idx'
12
+ add_index ActsAsTaggableOn.taggings_table,
13
+ [:tag_id, :taggable_id, :taggable_type, :context, :tagger_id, :tagger_type],
14
+ unique: true, name: 'taggings_idx'
15
+ end
16
+
17
+ def self.down
18
+ remove_index ActsAsTaggableOn.tags_table, :name
19
+
20
+ remove_index ActsAsTaggableOn.taggings_table, name: 'taggings_idx'
21
+
22
+ add_index ActsAsTaggableOn.taggings_table, :tag_id unless index_exists?(ActsAsTaggableOn.taggings_table, :tag_id)
23
+ add_index ActsAsTaggableOn.taggings_table, [:taggable_id, :taggable_type, :context], name: 'taggings_taggable_context_idx'
24
+ end
25
+ end
@@ -0,0 +1,19 @@
1
+ if ActiveRecord.gem_version >= Gem::Version.new('5.0')
2
+ class AddTaggingsCounterCacheToTags < ActiveRecord::Migration[4.2]; end
3
+ else
4
+ class AddTaggingsCounterCacheToTags < ActiveRecord::Migration; end
5
+ end
6
+ AddTaggingsCounterCacheToTags.class_eval do
7
+ def self.up
8
+ add_column ActsAsTaggableOn.tags_table, :taggings_count, :integer, default: 0
9
+
10
+ ActsAsTaggableOn::Tag.reset_column_information
11
+ ActsAsTaggableOn::Tag.find_each do |tag|
12
+ ActsAsTaggableOn::Tag.reset_counters(tag.id, ActsAsTaggableOn.taggings_table)
13
+ end
14
+ end
15
+
16
+ def self.down
17
+ remove_column ActsAsTaggableOn.tags_table, :taggings_count
18
+ end
19
+ end
@@ -0,0 +1,14 @@
1
+ if ActiveRecord.gem_version >= Gem::Version.new('5.0')
2
+ class AddMissingTaggableIndex < ActiveRecord::Migration[4.2]; end
3
+ else
4
+ class AddMissingTaggableIndex < ActiveRecord::Migration; end
5
+ end
6
+ AddMissingTaggableIndex.class_eval do
7
+ def self.up
8
+ add_index ActsAsTaggableOn.taggings_table, [:taggable_id, :taggable_type, :context], name: 'taggings_taggable_context_idx'
9
+ end
10
+
11
+ def self.down
12
+ remove_index ActsAsTaggableOn.taggings_table, name: 'taggings_taggable_context_idx'
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ # This migration is added to circumvent issue #623 and have special characters
2
+ # work properly
3
+ if ActiveRecord.gem_version >= Gem::Version.new('5.0')
4
+ class ChangeCollationForTagNames < ActiveRecord::Migration[4.2]; end
5
+ else
6
+ class ChangeCollationForTagNames < ActiveRecord::Migration; end
7
+ end
8
+ ChangeCollationForTagNames.class_eval do
9
+ def up
10
+ if ActsAsTaggableOn::Utils.using_mysql?
11
+ execute("ALTER TABLE #{ActsAsTaggableOn.tags_table} MODIFY name varchar(255) CHARACTER SET utf8 COLLATE utf8_bin;")
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,22 @@
1
+ if ActiveRecord.gem_version >= Gem::Version.new('5.0')
2
+ class AddMissingIndexesOnTaggings < ActiveRecord::Migration[4.2]; end
3
+ else
4
+ class AddMissingIndexesOnTaggings < ActiveRecord::Migration; end
5
+ end
6
+ AddMissingIndexesOnTaggings.class_eval do
7
+ def change
8
+ add_index ActsAsTaggableOn.taggings_table, :tag_id unless index_exists? ActsAsTaggableOn.taggings_table, :tag_id
9
+ add_index ActsAsTaggableOn.taggings_table, :taggable_id unless index_exists? ActsAsTaggableOn.taggings_table, :taggable_id
10
+ add_index ActsAsTaggableOn.taggings_table, :taggable_type unless index_exists? ActsAsTaggableOn.taggings_table, :taggable_type
11
+ add_index ActsAsTaggableOn.taggings_table, :tagger_id unless index_exists? ActsAsTaggableOn.taggings_table, :tagger_id
12
+ add_index ActsAsTaggableOn.taggings_table, :context unless index_exists? ActsAsTaggableOn.taggings_table, :context
13
+
14
+ unless index_exists? ActsAsTaggableOn.taggings_table, [:tagger_id, :tagger_type]
15
+ add_index ActsAsTaggableOn.taggings_table, [:tagger_id, :tagger_type]
16
+ end
17
+
18
+ unless index_exists? ActsAsTaggableOn.taggings_table, [:taggable_id, :taggable_type, :tagger_id, :context], name: 'taggings_idy'
19
+ add_index ActsAsTaggableOn.taggings_table, [:taggable_id, :taggable_type, :tagger_id, :context], name: 'taggings_idy'
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "activerecord", "~> 5.0.3"
4
+ case ENV["DB"]
5
+ when "postgresql"
6
+ gem 'pg'
7
+ when "mysql"
8
+ gem 'mysql2', '~> 0.3'
9
+ else
10
+ gem "sqlite3", "~> 1.3", "< 1.4"
11
+ end
12
+
13
+ group :local_development do
14
+ gem "guard"
15
+ gem "guard-rspec"
16
+ gem "appraisal"
17
+ gem "rake"
18
+ gem "byebug", platforms: [:mri]
19
+ end
20
+
21
+ gemspec path: "../"
@@ -0,0 +1,21 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "activerecord", "~> 5.1.1"
4
+ case ENV["DB"]
5
+ when "postgresql"
6
+ gem 'pg'
7
+ when "mysql"
8
+ gem 'mysql2', '~> 0.3'
9
+ else
10
+ gem "sqlite3", "~> 1.3", "< 1.4"
11
+ end
12
+
13
+ group :local_development do
14
+ gem "guard"
15
+ gem "guard-rspec"
16
+ gem "appraisal"
17
+ gem "rake"
18
+ gem "byebug", platforms: [:mri]
19
+ end
20
+
21
+ gemspec path: "../"
@@ -0,0 +1,21 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "activerecord", "~> 5.2.0"
4
+ case ENV["DB"]
5
+ when "postgresql"
6
+ gem 'pg'
7
+ when "mysql"
8
+ gem 'mysql2', '~> 0.3'
9
+ else
10
+ gem "sqlite3", "~> 1.3", "< 1.4"
11
+ end
12
+
13
+ group :local_development do
14
+ gem "guard"
15
+ gem "guard-rspec"
16
+ gem "appraisal"
17
+ gem "rake"
18
+ gem "byebug", platforms: [:mri]
19
+ end
20
+
21
+ gemspec path: "../"
@@ -0,0 +1,21 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "activerecord", "~> 6.0.0"
4
+ case ENV["DB"]
5
+ when "postgresql"
6
+ gem 'pg'
7
+ when "mysql"
8
+ gem 'mysql2', '~> 0.3'
9
+ else
10
+ gem 'sqlite3'
11
+ end
12
+
13
+ group :local_development do
14
+ gem "guard"
15
+ gem "guard-rspec"
16
+ gem "appraisal"
17
+ gem "rake"
18
+ gem "byebug", platforms: [:mri]
19
+ end
20
+
21
+ gemspec path: "../"
@@ -0,0 +1,133 @@
1
+ require 'active_record'
2
+ require 'active_record/version'
3
+ require 'active_support/core_ext/module'
4
+
5
+ begin
6
+ require 'rails/engine'
7
+ require 'acts_as_taggable_on/engine'
8
+ rescue LoadError
9
+
10
+ end
11
+
12
+ require 'digest/sha1'
13
+
14
+ module ActsAsTaggableOn
15
+ extend ActiveSupport::Autoload
16
+
17
+ autoload :Tag
18
+ autoload :TagList
19
+ autoload :GenericParser
20
+ autoload :DefaultParser
21
+ autoload :Taggable
22
+ autoload :Tagger
23
+ autoload :Tagging
24
+ autoload :TagsHelper
25
+ autoload :VERSION
26
+
27
+ autoload_under 'taggable' do
28
+ autoload :Cache
29
+ autoload :Collection
30
+ autoload :Core
31
+ autoload :Dirty
32
+ autoload :Ownership
33
+ autoload :Related
34
+ autoload :TagListType
35
+ end
36
+
37
+ autoload :Utils
38
+ autoload :Compatibility
39
+
40
+
41
+ class DuplicateTagError < StandardError
42
+ end
43
+
44
+ def self.setup
45
+ @configuration ||= Configuration.new
46
+ yield @configuration if block_given?
47
+ end
48
+
49
+ def self.method_missing(method_name, *args, &block)
50
+ @configuration.respond_to?(method_name) ?
51
+ @configuration.send(method_name, *args, &block) : super
52
+ end
53
+
54
+ def self.respond_to?(method_name, include_private=false)
55
+ @configuration.respond_to? method_name
56
+ end
57
+
58
+ def self.glue
59
+ setting = @configuration.delimiter
60
+ delimiter = setting.kind_of?(Array) ? setting[0] : setting
61
+ delimiter.ends_with?(' ') ? delimiter : "#{delimiter} "
62
+ end
63
+
64
+ class Configuration
65
+ attr_accessor :force_lowercase, :force_parameterize,
66
+ :remove_unused_tags, :default_parser,
67
+ :tags_counter, :tags_table,
68
+ :taggings_table
69
+ attr_reader :delimiter, :strict_case_match
70
+
71
+ def initialize
72
+ @delimiter = ','
73
+ @force_lowercase = false
74
+ @force_parameterize = false
75
+ @strict_case_match = false
76
+ @remove_unused_tags = false
77
+ @tags_counter = true
78
+ @default_parser = DefaultParser
79
+ @force_binary_collation = false
80
+ @tags_table = :tags
81
+ @taggings_table = :taggings
82
+ end
83
+
84
+ def strict_case_match=(force_cs)
85
+ @strict_case_match = force_cs unless @force_binary_collation
86
+ end
87
+
88
+ def delimiter=(string)
89
+ ActiveRecord::Base.logger.warn <<WARNING
90
+ ActsAsTaggableOn.delimiter is deprecated \
91
+ and will be removed from v4.0+, use \
92
+ a ActsAsTaggableOn.default_parser instead
93
+ WARNING
94
+ @delimiter = string
95
+ end
96
+
97
+ def force_binary_collation=(force_bin)
98
+ if Utils.using_mysql?
99
+ if force_bin
100
+ Configuration.apply_binary_collation(true)
101
+ @force_binary_collation = true
102
+ @strict_case_match = true
103
+ else
104
+ Configuration.apply_binary_collation(false)
105
+ @force_binary_collation = false
106
+ end
107
+ end
108
+ end
109
+
110
+ def self.apply_binary_collation(bincoll)
111
+ if Utils.using_mysql?
112
+ coll = 'utf8_general_ci'
113
+ coll = 'utf8_bin' if bincoll
114
+ begin
115
+ ActiveRecord::Migration.execute("ALTER TABLE #{Tag.table_name} MODIFY name varchar(255) CHARACTER SET utf8 COLLATE #{coll};")
116
+ rescue Exception => e
117
+ puts "Trapping #{e.class}: collation parameter ignored while migrating for the first time."
118
+ end
119
+ end
120
+ end
121
+
122
+ end
123
+
124
+ setup
125
+ end
126
+
127
+ ActiveSupport.on_load(:active_record) do
128
+ extend ActsAsTaggableOn::Taggable
129
+ include ActsAsTaggableOn::Tagger
130
+ end
131
+ ActiveSupport.on_load(:action_view) do
132
+ include ActsAsTaggableOn::TagsHelper
133
+ end
@@ -0,0 +1,6 @@
1
+ $stderr.puts <<EOF
2
+ You are requiring 'acts_as_taggable_on' in the 'acts-as-taggable-on' gem.
3
+
4
+ Please change your require to 'acts-as-taggable-on'.
5
+ EOF
6
+ require_relative 'acts-as-taggable-on'
@@ -0,0 +1,79 @@
1
+ module ActsAsTaggableOn
2
+ ##
3
+ # Returns a new TagList using the given tag string.
4
+ #
5
+ # Example:
6
+ # tag_list = ActsAsTaggableOn::DefaultParser.parse("One , Two, Three")
7
+ # tag_list # ["One", "Two", "Three"]
8
+ class DefaultParser < GenericParser
9
+
10
+ def parse
11
+ string = @tag_list
12
+
13
+ string = string.join(ActsAsTaggableOn.glue) if string.respond_to?(:join)
14
+ TagList.new.tap do |tag_list|
15
+ string = string.to_s.dup
16
+
17
+ string.gsub!(double_quote_pattern) {
18
+ # Append the matched tag to the tag list
19
+ tag_list << Regexp.last_match[2]
20
+ # Return the matched delimiter ($3) to replace the matched items
21
+ ''
22
+ }
23
+
24
+ string.gsub!(single_quote_pattern) {
25
+ # Append the matched tag ($2) to the tag list
26
+ tag_list << Regexp.last_match[2]
27
+ # Return an empty string to replace the matched items
28
+ ''
29
+ }
30
+
31
+ # split the string by the delimiter
32
+ # and add to the tag_list
33
+ tag_list.add(string.split(Regexp.new delimiter))
34
+ end
35
+ end
36
+
37
+
38
+ # private
39
+ def delimiter
40
+ # Parse the quoted tags
41
+ d = ActsAsTaggableOn.delimiter
42
+ # Separate multiple delimiters by bitwise operator
43
+ d = d.join('|') if d.kind_of?(Array)
44
+ d
45
+ end
46
+
47
+ # ( # Tag start delimiter ($1)
48
+ # \A | # Either string start or
49
+ # #{delimiter} # a delimiter
50
+ # )
51
+ # \s*" # quote (") optionally preceded by whitespace
52
+ # (.*?) # Tag ($2)
53
+ # "\s* # quote (") optionally followed by whitespace
54
+ # (?= # Tag end delimiter (not consumed; is zero-length lookahead)
55
+ # #{delimiter}\s* | # Either a delimiter optionally followed by whitespace or
56
+ # \z # string end
57
+ # )
58
+ def double_quote_pattern
59
+ /(\A|#{delimiter})\s*"(.*?)"\s*(?=#{delimiter}\s*|\z)/
60
+ end
61
+
62
+ # ( # Tag start delimiter ($1)
63
+ # \A | # Either string start or
64
+ # #{delimiter} # a delimiter
65
+ # )
66
+ # \s*' # quote (') optionally preceded by whitespace
67
+ # (.*?) # Tag ($2)
68
+ # '\s* # quote (') optionally followed by whitespace
69
+ # (?= # Tag end delimiter (not consumed; is zero-length lookahead)
70
+ # #{delimiter}\s* | d # Either a delimiter optionally followed by whitespace or
71
+ # \z # string end
72
+ # )
73
+ def single_quote_pattern
74
+ /(\A|#{delimiter})\s*'(.*?)'\s*(?=#{delimiter}\s*|\z)/
75
+ end
76
+
77
+ end
78
+
79
+ end