acts-as-taggable-on 3.5.0 → 4.0.0.pre

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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.travis.yml +14 -18
  4. data/Appraisals +9 -8
  5. data/CHANGELOG.md +3 -1
  6. data/Gemfile +1 -1
  7. data/README.md +41 -3
  8. data/acts-as-taggable-on.gemspec +3 -3
  9. data/db/migrate/2_add_missing_unique_indices.rb +3 -2
  10. data/db/migrate/6_add_missing_indexes.rb +12 -0
  11. data/gemfiles/activerecord_4.0.gemfile +3 -2
  12. data/gemfiles/activerecord_4.1.gemfile +3 -2
  13. data/gemfiles/activerecord_4.2.gemfile +2 -3
  14. data/gemfiles/{activerecord_3.2.gemfile → activerecord_5.0.gemfile} +2 -2
  15. data/lib/acts-as-taggable-on.rb +16 -12
  16. data/lib/acts_as_taggable_on/engine.rb +0 -1
  17. data/lib/acts_as_taggable_on/tag.rb +6 -2
  18. data/lib/acts_as_taggable_on/tag_list.rb +2 -13
  19. data/lib/acts_as_taggable_on/taggable/cache.rb +1 -1
  20. data/lib/acts_as_taggable_on/taggable/collection.rb +6 -3
  21. data/lib/acts_as_taggable_on/taggable/core.rb +21 -16
  22. data/lib/acts_as_taggable_on/taggable/ownership.rb +3 -3
  23. data/lib/acts_as_taggable_on/tagger.rb +12 -11
  24. data/lib/acts_as_taggable_on/tagging.rb +4 -14
  25. data/lib/acts_as_taggable_on/utils.rb +2 -3
  26. data/lib/acts_as_taggable_on/version.rb +1 -1
  27. data/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb +10 -1
  28. data/spec/acts_as_taggable_on/acts_as_tagger_spec.rb +1 -1
  29. data/spec/acts_as_taggable_on/caching_spec.rb +22 -0
  30. data/spec/acts_as_taggable_on/tag_list_spec.rb +27 -1
  31. data/spec/acts_as_taggable_on/tag_spec.rb +15 -0
  32. data/spec/acts_as_taggable_on/taggable_spec.rb +19 -5
  33. data/spec/acts_as_taggable_on/tagging_spec.rb +64 -10
  34. data/spec/internal/db/schema.rb +7 -3
  35. data/spec/support/database.rb +1 -7
  36. metadata +12 -21
  37. data/lib/acts_as_taggable_on/compatibility.rb +0 -35
  38. data/lib/acts_as_taggable_on/tag_list_parser.rb +0 -21
  39. data/spec/acts_as_taggable_on/tag_list_parser_spec.rb +0 -46
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 92222646174fc38e87d9972cea2022c78e9ba337
4
- data.tar.gz: 62d819d54ea8d538ce67d1f30c4c640e63333328
3
+ metadata.gz: 8c10b1bdc1cfdce1f5faa7db0cb813257657bcda
4
+ data.tar.gz: fdc07fbeaf0a0fe45e1410b2f6a52078a168ff8d
5
5
  SHA512:
6
- metadata.gz: 6a17ce74f9d91e98037faa3348449813632f2f1ba2a4ca92a297beaafa8e544b650c2e12586c03a9aab8c2c6b0b5c1c1de21571d860be49aed971b0d20b8338e
7
- data.tar.gz: d50ea8e8200c3eaef6f1d80b53412637604e74de62dd3a2e6385e22d1fbf579bbb372f2bbd9b6c026f3f062e4959a288a5a890360d5f98cde6df222ebc72947f
6
+ metadata.gz: 1542dd8c7ebafeed4794f6f734da1e98f9641d7ddda18fa93c7e49ec4d5b14867353e065a6f3598050d0606f3e2809c5034a07c9f91385f22c90159dad202c50
7
+ data.tar.gz: aba26b02cbc655676003bfb6d73092ab49dae44013985a6838b187b3f4920507e684e73fab8a53c7d8b11e036cbc58a608943e3116ebee4ff10bf7df8fea6e80
data/.gitignore CHANGED
@@ -9,3 +9,5 @@ tmp*.sw?
9
9
  tmp
10
10
  *.gem
11
11
  *.lock
12
+
13
+ /.idea
@@ -1,11 +1,11 @@
1
1
  language: ruby
2
+ cache: bundler
2
3
 
3
4
  rvm:
5
+ - 2.3.1
6
+ - 2.2.5
4
7
  - 2.1
5
- - 2.2
6
8
  - 2.0.0
7
- - 1.9.3
8
- - rbx-2
9
9
 
10
10
  env:
11
11
  - DB=sqlite3
@@ -13,28 +13,24 @@ env:
13
13
  - DB=postgresql
14
14
 
15
15
  gemfile:
16
- - gemfiles/activerecord_3.2.gemfile
17
- - gemfiles/activerecord_4.0.gemfile
16
+ - gemfiles/activerecord_5.0.gemfile
17
+ - gemfiles/activerecord_4.2.gemfile
18
18
  - gemfiles/activerecord_4.1.gemfile
19
+ - gemfiles/activerecord_4.0.gemfile
19
20
 
20
21
  sudo: false
21
22
 
22
23
  bundler_args: '--without local_development --jobs 3 --retry 3'
23
24
 
25
+ before_install:
26
+ - gem install bundler
27
+
24
28
  script: bundle exec rake
25
29
 
26
30
  matrix:
27
- fast_finish: true
28
- allow_failures:
29
- - gemfile: gemfiles/activerecord_edge.gemfile
30
- - rvm: rbx-2
31
31
  exclude:
32
- - rvm: 2.2
33
- gemfile: gemfiles/activerecord_3.2.gemfile
34
- - rvm: 1.9.3
35
- gemfile: gemfiles/activerecord_4.0.gemfile
36
- - rvm: 1.9.3
37
- gemfile: gemfiles/activerecord_4.1.gemfile
38
- - rvm: rbx-2
39
- gemfile: gemfiles/activerecord_3.2.gemfile
40
-
32
+ - rvm: 2.0.0
33
+ gemfile: gemfiles/activerecord_5.0.gemfile
34
+ - rvm: 2.1
35
+ gemfile: gemfiles/activerecord_5.0.gemfile
36
+ fast_finish: true
data/Appraisals CHANGED
@@ -1,16 +1,17 @@
1
- appraise "activerecord-3.2" do
2
- gem "activerecord", github: "rails/rails" , branch: '3-2-stable'
1
+ appraise 'activerecord-5.0' do
2
+ gem 'activerecord', "~> 5.0.0"
3
3
  end
4
4
 
5
- appraise "activerecord-4.0" do
6
- gem "activerecord", github: "rails/rails" , branch: '4-0-stable'
5
+ appraise "activerecord-4.2" do
6
+ gem "activerecord", "~> 4.2.0"
7
7
  end
8
8
 
9
9
  appraise "activerecord-4.1" do
10
- gem "activerecord", github: "rails/rails" , branch: '4-1-stable'
10
+ gem "activerecord", "~> 4.1.0"
11
+ gem 'mysql2', '~> 0.3.21'
11
12
  end
12
13
 
13
- appraise "activerecord-4.2" do
14
- gem "railties", github: "rails/rails" , branch: '4-2-stable'
15
- gem "activerecord", github: "rails/rails" , branch: '4-2-stable'
14
+ appraise "activerecord-4.0" do
15
+ gem "activerecord", "~> 4.0.0"
16
+ gem 'mysql2', '~> 0.3.21'
16
17
  end
@@ -4,10 +4,12 @@ Each change should fall into categories that would affect whether the release is
4
4
 
5
5
  As such, a _Feature_ would map to either major or minor. A _bug fix_ to a patch. And _misc_ is either minor or patch, the difference being kind of fuzzy for the purposes of history. Adding tests would be patch level.
6
6
 
7
- ### [3.5.0 / 2015-02-11](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.4.4...v3.5.0)
7
+ ### [3.5.0 / 2015-03-03](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.4.4...v3.5.0)
8
8
 
9
9
  * Fixes
10
10
  * [@rikettsie Fixed collation for MySql via rake rule or config parameter](https://github.com/mbleigh/acts-as-taggable-on/pull/634)
11
+ *Misc
12
+ * [@pcupueran Add rspec test for tagging_spec completeness]()
11
13
 
12
14
  ### [3.4.4 / 2015-02-11](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.4.3...v3.4.4)
13
15
 
data/Gemfile CHANGED
@@ -7,5 +7,5 @@ group :local_development do
7
7
  gem 'guard-rspec'
8
8
  gem 'appraisal'
9
9
  gem 'rake'
10
- gem 'byebug' , platform: :mri_21
10
+ gem 'byebug' , platforms: [:mri_21, :mri_22, :mri_23]
11
11
  end
data/README.md CHANGED
@@ -1,4 +1,6 @@
1
1
  # ActsAsTaggableOn
2
+
3
+ [![Join the chat at https://gitter.im/mbleigh/acts-as-taggable-on](https://badges.gitter.im/mbleigh/acts-as-taggable-on.svg)](https://gitter.im/mbleigh/acts-as-taggable-on?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
2
4
  [![Gem Version](https://badge.fury.io/rb/acts-as-taggable-on.svg)](http://badge.fury.io/rb/acts-as-taggable-on)
3
5
  [![Build Status](https://secure.travis-ci.org/mbleigh/acts-as-taggable-on.png)](http://travis-ci.org/mbleigh/acts-as-taggable-on)
4
6
  [![Code Climate](https://codeclimate.com/github/mbleigh/acts-as-taggable-on.png)](https://codeclimate.com/github/mbleigh/acts-as-taggable-on)
@@ -89,7 +91,7 @@ end
89
91
 
90
92
  class UsersController < ApplicationController
91
93
  def user_params
92
- params.require(:user).permit(:name, :tag_list => []) ## Rails 4 strong params usage
94
+ params.require(:user).permit(:name, :tag_list) ## Rails 4 strong params usage
93
95
  end
94
96
  end
95
97
 
@@ -273,7 +275,7 @@ User.tagged_with("same", :on => :customs) # => [@user]
273
275
 
274
276
  ### Tag Parsers
275
277
 
276
- If you want to change how tags are parsed, you can define a your own implementation:
278
+ If you want to change how tags are parsed, you can define your own implementation:
277
279
 
278
280
  ```ruby
279
281
  class MyParser < ActsAsTaggableOn::GenericParser
@@ -302,7 +304,7 @@ Now you can use this parser, passing it as parameter:
302
304
  Or change it globally:
303
305
 
304
306
  ```ruby
305
- ActsAsTaggable.default_parser = MyParser
307
+ ActsAsTaggableOn.default_parser = MyParser
306
308
  @user = User.new(:name => "Bobby")
307
309
  @user.tag_list = "east|south"
308
310
  @user.tag_list # => ["east", "south"]
@@ -331,6 +333,42 @@ Photo.tagged_with("paris", :on => :locations, :owned_by => @some_user)
331
333
  @some_user.tag(@some_photo, :with => "paris, normandy", :on => :locations, :skip_save => true) #won't save @some_photo object
332
334
  ```
333
335
 
336
+ #### Working with Owned Tags
337
+ Note that `tag_list` only returns tags whose taggings do not have an owner. Continuing from the above example:
338
+ ```ruby
339
+ @some_photo.tag_list # => []
340
+ ```
341
+ To retrieve all tags of an object (regardless of ownership) or if only one owner can tag the object, use `all_tags_list`.
342
+
343
+ ##### Adding owned tags
344
+ Note that **owned tags** are added all at once, in the form of ***comma seperated tags*** in string.
345
+ Also, when you try to add **owned tags** again, it simply overwrites the previous set of **owned tags**.
346
+ So to append tags in previously existing **owned tags** list, go as follows:
347
+ ```ruby
348
+ def add_owned_tag
349
+ @some_item = Item.find(params[:id])
350
+ owned_tag_list = @some_item.all_tag_list - @some_item.tag_list
351
+ owned_tag_list += [(params[:tag])]
352
+ @tag_owner.tag(@some_item, :with => stringify(owned_tag_list), :on => :tags)
353
+ @some_item.save
354
+ end
355
+
356
+ def stringify(tag_list)
357
+ tag_list.inject('') { |memo, tag| memo += (tag + ',') }[0..-1]
358
+ end
359
+ ```
360
+ ##### Removing owned tags
361
+ Similarly as above, removing will be as follows:
362
+ ```ruby
363
+ def remove_owned_tag
364
+ @some_item = Item.find(params[:id])
365
+ owned_tag_list = @some_item.all_tag_list - @some_item.tag_list
366
+ owned_tag_list -= [(params[:tag])]
367
+ @tag_owner.tag(@some_item, :with => stringify(owned_tag_list), :on => :tags)
368
+ @some_item.save
369
+ end
370
+ ```
371
+
334
372
  ### Dirty objects
335
373
 
336
374
  ```ruby
@@ -16,16 +16,16 @@ Gem::Specification.new do |gem|
16
16
  gem.files = `git ls-files`.split($/)
17
17
  gem.test_files = gem.files.grep(%r{^spec/})
18
18
  gem.require_paths = ['lib']
19
- gem.required_ruby_version = '>= 1.9.3'
19
+ gem.required_ruby_version = '>= 2.0.0'
20
20
 
21
21
  if File.exist?('UPGRADING.md')
22
22
  gem.post_install_message = File.read('UPGRADING.md')
23
23
  end
24
24
 
25
- gem.add_runtime_dependency 'activerecord', ['>= 3.2', '< 5']
25
+ gem.add_runtime_dependency 'activerecord', ['>= 4.0']
26
26
 
27
27
  gem.add_development_dependency 'sqlite3'
28
- gem.add_development_dependency 'mysql2', '~> 0.3.7'
28
+ gem.add_development_dependency 'mysql2', '~> 0.3'
29
29
  gem.add_development_dependency 'pg'
30
30
 
31
31
  gem.add_development_dependency 'rspec-rails'
@@ -2,7 +2,7 @@ class AddMissingUniqueIndices < ActiveRecord::Migration
2
2
  def self.up
3
3
  add_index :tags, :name, unique: true
4
4
 
5
- remove_index :taggings, :tag_id
5
+ remove_index :taggings, :tag_id if index_exists?(:taggings, :tag_id)
6
6
  remove_index :taggings, [:taggable_id, :taggable_type, :context]
7
7
  add_index :taggings,
8
8
  [:tag_id, :taggable_id, :taggable_type, :context, :tagger_id, :tagger_type],
@@ -13,7 +13,8 @@ class AddMissingUniqueIndices < ActiveRecord::Migration
13
13
  remove_index :tags, :name
14
14
 
15
15
  remove_index :taggings, name: 'taggings_idx'
16
- add_index :taggings, :tag_id
16
+
17
+ add_index :taggings, :tag_id unless index_exists?(:taggings, :tag_id)
17
18
  add_index :taggings, [:taggable_id, :taggable_type, :context]
18
19
  end
19
20
  end
@@ -0,0 +1,12 @@
1
+ class AddMissingIndexes < ActiveRecord::Migration
2
+ def change
3
+ add_index :taggings, :tag_id
4
+ add_index :taggings, :taggable_id
5
+ add_index :taggings, :taggable_type
6
+ add_index :taggings, :tagger_id
7
+ add_index :taggings, :context
8
+
9
+ add_index :taggings, [:tagger_id, :tagger_type]
10
+ add_index :taggings, [:taggable_id, :taggable_type, :tagger_id, :context], name: 'taggings_idy'
11
+ end
12
+ end
@@ -2,14 +2,15 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "activerecord", :github => "rails/rails", :branch => "4-0-stable"
5
+ gem "activerecord", "~> 4.0.0"
6
+ gem "mysql2", "~> 0.3.21"
6
7
 
7
8
  group :local_development do
8
9
  gem "guard"
9
10
  gem "guard-rspec"
10
11
  gem "appraisal"
11
12
  gem "rake"
12
- gem "byebug", :platform => :mri_21
13
+ gem "byebug", :platforms => [:mri_21, :mri_22, :mri_23]
13
14
  end
14
15
 
15
16
  gemspec :path => "../"
@@ -2,14 +2,15 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "activerecord", :github => "rails/rails", :branch => "4-1-stable"
5
+ gem "activerecord", "~> 4.1.0"
6
+ gem "mysql2", "~> 0.3.21"
6
7
 
7
8
  group :local_development do
8
9
  gem "guard"
9
10
  gem "guard-rspec"
10
11
  gem "appraisal"
11
12
  gem "rake"
12
- gem "byebug", :platform => :mri_21
13
+ gem "byebug", :platforms => [:mri_21, :mri_22, :mri_23]
13
14
  end
14
15
 
15
16
  gemspec :path => "../"
@@ -2,15 +2,14 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "railties", :github => "rails/rails", :branch => "4-2-stable"
6
- gem "activerecord", :github => "rails/rails", :branch => "4-2-stable"
5
+ gem "activerecord", "~> 4.2.0"
7
6
 
8
7
  group :local_development do
9
8
  gem "guard"
10
9
  gem "guard-rspec"
11
10
  gem "appraisal"
12
11
  gem "rake"
13
- gem "byebug", :platform => :mri_21
12
+ gem "byebug", :platforms => [:mri_21, :mri_22, :mri_23]
14
13
  end
15
14
 
16
15
  gemspec :path => "../"
@@ -2,14 +2,14 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "activerecord", :github => "rails/rails", :branch => "3-2-stable"
5
+ gem "activerecord", "~> 5.0.0"
6
6
 
7
7
  group :local_development do
8
8
  gem "guard"
9
9
  gem "guard-rspec"
10
10
  gem "appraisal"
11
11
  gem "rake"
12
- gem "byebug", :platform => :mri_21
12
+ gem "byebug", :platforms => [:mri_21, :mri_22, :mri_23]
13
13
  end
14
14
 
15
15
  gemspec :path => "../"
@@ -2,7 +2,12 @@ require 'active_record'
2
2
  require 'active_record/version'
3
3
  require 'active_support/core_ext/module'
4
4
 
5
- require_relative 'acts_as_taggable_on/engine' if defined?(Rails)
5
+ begin
6
+ require 'rails/engine'
7
+ require 'acts_as_taggable_on/engine'
8
+ rescue LoadError
9
+
10
+ end
6
11
 
7
12
  require 'digest/sha1'
8
13
 
@@ -13,7 +18,6 @@ module ActsAsTaggableOn
13
18
  autoload :TagList
14
19
  autoload :GenericParser
15
20
  autoload :DefaultParser
16
- autoload :TagListParser
17
21
  autoload :Taggable
18
22
  autoload :Tagger
19
23
  autoload :Tagging
@@ -57,9 +61,10 @@ module ActsAsTaggableOn
57
61
  end
58
62
 
59
63
  class Configuration
60
- attr_accessor :delimiter, :force_lowercase, :force_parameterize,
61
- :strict_case_match, :remove_unused_tags, :default_parser,
64
+ attr_accessor :force_lowercase, :force_parameterize,
65
+ :remove_unused_tags, :default_parser,
62
66
  :tags_counter
67
+ attr_reader :delimiter, :strict_case_match
63
68
 
64
69
  def initialize
65
70
  @delimiter = ','
@@ -73,9 +78,7 @@ module ActsAsTaggableOn
73
78
  end
74
79
 
75
80
  def strict_case_match=(force_cs)
76
- if @force_binary_collation == false
77
- @strict_case_match = force_cs
78
- end
81
+ @strict_case_match = force_cs unless @force_binary_collation
79
82
  end
80
83
 
81
84
  def delimiter=(string)
@@ -89,7 +92,7 @@ WARNING
89
92
 
90
93
  def force_binary_collation=(force_bin)
91
94
  if Utils.using_mysql?
92
- if force_bin == true
95
+ if force_bin
93
96
  Configuration.apply_binary_collation(true)
94
97
  @force_binary_collation = true
95
98
  @strict_case_match = true
@@ -103,10 +106,12 @@ WARNING
103
106
  def self.apply_binary_collation(bincoll)
104
107
  if Utils.using_mysql?
105
108
  coll = 'utf8_general_ci'
106
- if bincoll == true
107
- coll = 'utf8_bin'
109
+ coll = 'utf8_bin' if bincoll
110
+ begin
111
+ ActiveRecord::Migration.execute("ALTER TABLE #{Tag.table_name} MODIFY name varchar(255) CHARACTER SET utf8 COLLATE #{coll};")
112
+ rescue Exception => e
113
+ puts "Trapping #{e.class}: collation parameter ignored while migrating for the first time."
108
114
  end
109
- ActiveRecord::Migration.execute("ALTER TABLE tags MODIFY name varchar(255) CHARACTER SET utf8 COLLATE #{coll};")
110
115
  end
111
116
  end
112
117
 
@@ -116,7 +121,6 @@ WARNING
116
121
  end
117
122
 
118
123
  ActiveSupport.on_load(:active_record) do
119
- extend ActsAsTaggableOn::Compatibility
120
124
  extend ActsAsTaggableOn::Taggable
121
125
  include ActsAsTaggableOn::Tagger
122
126
  end
@@ -1,4 +1,3 @@
1
- require 'rails/engine'
2
1
  module ActsAsTaggableOn
3
2
  class Engine < Rails::Engine
4
3
  end
@@ -2,8 +2,6 @@
2
2
  module ActsAsTaggableOn
3
3
  class Tag < ::ActiveRecord::Base
4
4
 
5
- attr_accessible :name if defined?(ActiveModel::MassAssignmentSecurity)
6
-
7
5
  ### ASSOCIATIONS:
8
6
 
9
7
  has_many :taggings, dependent: :destroy, class_name: '::ActsAsTaggableOn::Tagging'
@@ -50,6 +48,12 @@ module ActsAsTaggableOn
50
48
  where(clause)
51
49
  end
52
50
 
51
+ def self.for_context(context)
52
+ joins(:taggings).
53
+ where(["taggings.context = ?", context]).
54
+ select("DISTINCT tags.*")
55
+ end
56
+
53
57
  ### CLASS METHODS:
54
58
 
55
59
  def self.find_or_create_with_like_by_name(name)
@@ -84,7 +84,8 @@ module ActsAsTaggableOn
84
84
  map! { |tag| tag.mb_chars.downcase.to_s } if ActsAsTaggableOn.force_lowercase
85
85
  map!(&:parameterize) if ActsAsTaggableOn.force_parameterize
86
86
 
87
- uniq!
87
+ ActsAsTaggableOn.strict_case_match ? uniq! : uniq!{ |tag| tag.downcase }
88
+ self
88
89
  end
89
90
 
90
91
 
@@ -99,18 +100,6 @@ module ActsAsTaggableOn
99
100
  args.flatten!
100
101
  end
101
102
 
102
-
103
- ## DEPRECATED
104
- def self.from(string)
105
- ActiveRecord::Base.logger.warn <<WARNING
106
- ActsAsTaggableOn::TagList.from is deprecated \
107
- and will be removed from v4.0+, use \
108
- ActsAsTaggableOn::DefaultParser.new instead
109
- WARNING
110
- @parser.new(string).parse
111
- end
112
-
113
-
114
103
  end
115
104
  end
116
105
 
@@ -73,7 +73,7 @@ module ActsAsTaggableOn::Taggable
73
73
  tag_types.map(&:to_s).each do |tag_type|
74
74
  if self.class.send("caching_#{tag_type.singularize}_list?")
75
75
  if tag_list_cache_set_on(tag_type)
76
- list = tag_list_cache_on(tag_type).to_a.flatten.compact.join(', ')
76
+ list = tag_list_cache_on(tag_type).to_a.flatten.compact.join("#{ActsAsTaggableOn.delimiter} ")
77
77
  self["cached_#{tag_type.singularize}_list"] = list
78
78
  end
79
79
  end
@@ -138,7 +138,7 @@ module ActsAsTaggableOn::Taggable
138
138
  scoped_ids = pluck(table_name_pkey)
139
139
  tagging_scope = tagging_scope.where("#{ActsAsTaggableOn::Tagging.table_name}.taggable_id IN (?)", scoped_ids)
140
140
  else
141
- tagging_scope = tagging_scope.where("#{ActsAsTaggableOn::Tagging.table_name}.taggable_id IN(#{safe_to_sql(select(table_name_pkey))})")
141
+ tagging_scope = tagging_scope.where("#{ActsAsTaggableOn::Tagging.table_name}.taggable_id IN(#{safe_to_sql(except(:select).select(table_name_pkey))})")
142
142
  end
143
143
 
144
144
  tagging_scope
@@ -169,9 +169,12 @@ module ActsAsTaggableOn::Taggable
169
169
  end
170
170
 
171
171
  module CalculationMethods
172
- def count(column_name=:all, options = {})
172
+ # Rails 5 TODO: Remove options argument as soon we remove support to
173
+ # activerecord-deprecated_finders.
174
+ # See https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation/calculations.rb#L38
175
+ def count(column_name = :all, options = {})
173
176
  # https://github.com/rails/rails/commit/da9b5d4a8435b744fcf278fffd6d7f1e36d4a4f2
174
- super
177
+ ActsAsTaggableOn::Utils.active_record5? ? super(column_name) : super(column_name, options)
175
178
  end
176
179
  end
177
180
  end
@@ -23,18 +23,15 @@ module ActsAsTaggableOn::Taggable
23
23
  class_eval do
24
24
  # when preserving tag order, include order option so that for a 'tags' context
25
25
  # the associations tag_taggings & tags are always returned in created order
26
- has_many_with_taggable_compatibility context_taggings, as: :taggable,
27
- dependent: :destroy,
28
- class_name: 'ActsAsTaggableOn::Tagging',
29
- order: taggings_order,
30
- conditions: {context: tags_type},
31
- include: :tag
32
-
33
- has_many_with_taggable_compatibility context_tags, through: context_taggings,
34
- source: :tag,
35
- class_name: 'ActsAsTaggableOn::Tag',
36
- order: taggings_order
37
-
26
+ has_many context_taggings, -> { includes(:tag).order(taggings_order).where(context: tags_type) },
27
+ as: :taggable,
28
+ class_name: ActsAsTaggableOn::Tagging,
29
+ dependent: :destroy
30
+
31
+ has_many context_tags, -> { order(taggings_order) },
32
+ class_name: ActsAsTaggableOn::Tag,
33
+ through: context_taggings,
34
+ source: :tag
38
35
  end
39
36
 
40
37
  taggable_mixin.class_eval <<-RUBY, __FILE__, __LINE__ + 1
@@ -246,6 +243,14 @@ module ActsAsTaggableOn::Taggable
246
243
  def taggable_mixin
247
244
  @taggable_mixin ||= Module.new
248
245
  end
246
+
247
+ private
248
+
249
+ # Rails 5 has merged sanitize and quote_value
250
+ # See https://github.com/rails/rails/blob/master/activerecord/lib/active_record/sanitization.rb#L10
251
+ def quote_value(value, column = nil)
252
+ ActsAsTaggableOn::Utils.active_record5? ? super(value) : super(value, column)
253
+ end
249
254
  end
250
255
 
251
256
  # all column names are necessary for PostgreSQL group clause
@@ -254,7 +259,7 @@ module ActsAsTaggableOn::Taggable
254
259
  end
255
260
 
256
261
  def custom_contexts
257
- @custom_contexts ||= []
262
+ @custom_contexts ||= taggings.map(&:context).uniq
258
263
  end
259
264
 
260
265
  def is_taggable?
@@ -333,7 +338,7 @@ module ActsAsTaggableOn::Taggable
333
338
  end
334
339
 
335
340
  def tagging_contexts
336
- custom_contexts + self.class.tag_types.map(&:to_s)
341
+ self.class.tag_types.map(&:to_s) + custom_contexts
337
342
  end
338
343
 
339
344
  def process_dirty_object(context, new_list)
@@ -407,7 +412,7 @@ module ActsAsTaggableOn::Taggable
407
412
 
408
413
  # Destroy old taggings:
409
414
  if old_tags.present?
410
- taggings.not_owned.by_context(context).destroy_all(tag_id: old_tags)
415
+ taggings.not_owned.by_context(context).where(tag_id: old_tags).destroy_all
411
416
  end
412
417
 
413
418
  # Create new taggings:
@@ -432,7 +437,7 @@ module ActsAsTaggableOn::Taggable
432
437
  tag_lists = tag_types.map {|tags_type| "#{tags_type.to_s.singularize}_list"}
433
438
  super.delete_if {|attr| tag_lists.include? attr }
434
439
  end
435
-
440
+
436
441
  ##
437
442
  # Override this hook if you wish to subclass {ActsAsTaggableOn::Tag} --
438
443
  # context is provided so that you may conditionally use a Tag subclass
@@ -108,9 +108,9 @@ module ActsAsTaggableOn::Taggable
108
108
 
109
109
  # Find all taggings that belong to the taggable (self), are owned by the owner,
110
110
  # have the correct context, and are removed from the list.
111
- ActsAsTaggableOn::Tagging.destroy_all(taggable_id: id, taggable_type: self.class.base_class.to_s,
112
- tagger_type: owner.class.base_class.to_s, tagger_id: owner.id,
113
- tag_id: old_tags, context: context) if old_tags.present?
111
+ ActsAsTaggableOn::Tagging.where(taggable_id: id, taggable_type: self.class.base_class.to_s,
112
+ tagger_type: owner.class.base_class.to_s, tagger_id: owner.id,
113
+ tag_id: old_tags, context: context).destroy_all if old_tags.present?
114
114
 
115
115
  # Create new taggings:
116
116
  new_tags.each do |tag|
@@ -15,18 +15,19 @@ module ActsAsTaggableOn
15
15
  # end
16
16
  def acts_as_tagger(opts={})
17
17
  class_eval do
18
- has_many_with_taggable_compatibility :owned_taggings,
19
- opts.merge(
20
- as: :tagger,
21
- dependent: :destroy,
22
- class_name: '::ActsAsTaggableOn::Tagging'
23
- )
18
+ owned_taggings_scope = opts.delete(:scope)
24
19
 
25
- has_many_with_taggable_compatibility :owned_tags,
26
- through: :owned_taggings,
27
- source: :tag,
28
- class_name: '::ActsAsTaggableOn::Tag',
29
- uniq: true
20
+ has_many :owned_taggings, owned_taggings_scope,
21
+ opts.merge(
22
+ as: :tagger,
23
+ class_name: ::ActsAsTaggableOn::Tagging,
24
+ dependent: :destroy
25
+ )
26
+
27
+ has_many :owned_tags, -> { distinct },
28
+ class_name: ::ActsAsTaggableOn::Tag,
29
+ source: :tag,
30
+ through: :owned_taggings
30
31
  end
31
32
 
32
33
  include ActsAsTaggableOn::Tagger::InstanceMethods
@@ -1,25 +1,15 @@
1
1
  module ActsAsTaggableOn
2
2
  class Tagging < ::ActiveRecord::Base #:nodoc:
3
- #TODO, remove from 4.0.0
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 if defined?(ActiveModel::MassAssignmentSecurity)
13
-
14
3
  belongs_to :tag, class_name: '::ActsAsTaggableOn::Tag', counter_cache: ActsAsTaggableOn.tags_counter
15
4
  belongs_to :taggable, polymorphic: true
16
- belongs_to :tagger, polymorphic: true
5
+
6
+ belongs_to :tagger, {polymorphic: true}.tap {|o| o.merge!(optional: true) if ActsAsTaggableOn::Utils.active_record5? }
17
7
 
18
8
  scope :owned_by, ->(owner) { where(tagger: owner) }
19
9
  scope :not_owned, -> { where(tagger_id: nil, tagger_type: nil) }
20
10
 
21
- scope :by_contexts, ->(contexts = ['tags']) { where(context: contexts) }
22
- scope :by_context, ->(context= 'tags') { by_contexts(context.to_s) }
11
+ scope :by_contexts, ->(contexts) { where(context: (contexts || 'tags')) }
12
+ scope :by_context, ->(context = 'tags') { by_contexts(context.to_s) }
23
13
 
24
14
  validates_presence_of :context
25
15
  validates_presence_of :tag_id
@@ -13,7 +13,6 @@ module ActsAsTaggableOn
13
13
  end
14
14
 
15
15
  def using_mysql?
16
- #We should probably use regex for mysql to support prehistoric adapters
17
16
  connection && connection.adapter_name == 'Mysql2'
18
17
  end
19
18
 
@@ -21,8 +20,8 @@ module ActsAsTaggableOn
21
20
  Digest::SHA1.hexdigest(string)[0..6]
22
21
  end
23
22
 
24
- def active_record4?
25
- ::ActiveRecord::VERSION::MAJOR == 4
23
+ def active_record5?
24
+ ::ActiveRecord::VERSION::MAJOR == 5
26
25
  end
27
26
 
28
27
  def like_operator
@@ -1,4 +1,4 @@
1
1
  module ActsAsTaggableOn
2
- VERSION = '3.5.0'
2
+ VERSION = '4.0.0.pre'
3
3
  end
4
4
 
@@ -154,7 +154,7 @@ describe 'Acts As Taggable On' do
154
154
  describe 'Tagging Contexts' do
155
155
  it 'should eliminate duplicate tagging contexts ' do
156
156
  TaggableModel.acts_as_taggable_on(:skills, :skills)
157
- expect(TaggableModel.tag_types.freq[:skills]).to_not eq(3)
157
+ expect(TaggableModel.tag_types.freq[:skills]).to eq(1)
158
158
  end
159
159
 
160
160
  it 'should not contain embedded/nested arrays' do
@@ -178,6 +178,15 @@ describe 'Acts As Taggable On' do
178
178
  TaggableModel.acts_as_taggable_on([nil])
179
179
  }).to_not raise_error
180
180
  end
181
+
182
+ it 'should include dynamic contexts in tagging_contexts' do
183
+ taggable = TaggableModel.create!(name: 'Dynamic Taggable')
184
+ taggable.set_tag_list_on :colors, 'tag1, tag2, tag3'
185
+ expect(taggable.tagging_contexts).to eq(%w(tags languages skills needs offerings array colors))
186
+ taggable.save
187
+ taggable = TaggableModel.where(name: 'Dynamic Taggable').first
188
+ expect(taggable.tagging_contexts).to eq(%w(tags languages skills needs offerings array colors))
189
+ end
181
190
  end
182
191
 
183
192
  context 'when tagging context ends in an "s" when singular (ex. "status", "glass", etc.)' do
@@ -72,7 +72,7 @@ describe 'acts_as_tagger' do
72
72
  expect(@taggable.tag_list_on(:foo_boo)).to be_empty
73
73
  expect(-> {
74
74
  @tagger.tag(@taggable, with: 'this, and, that', on: :foo_boo, force: false)
75
- }).to raise_error
75
+ }).to raise_error(RuntimeError)
76
76
  end
77
77
 
78
78
  it 'should not create the tag context on-the-fly when the default is over-ridden' do
@@ -77,6 +77,28 @@ describe 'Acts As Taggable On' do
77
77
  end
78
78
  end
79
79
 
80
+ describe 'with a custom delimiter' do
81
+ before(:each) do
82
+ @taggable = CachedModel.new(name: 'Bob Jones')
83
+ @another_taggable = OtherCachedModel.new(name: 'John Smith')
84
+ ActsAsTaggableOn.delimiter = ';'
85
+ end
86
+
87
+ after(:all) do
88
+ ActsAsTaggableOn.delimiter = ','
89
+ end
90
+
91
+ it 'should cache tags with custom delimiter' do
92
+ @taggable.update_attributes(tag_list: 'awesome; epic')
93
+ expect(@taggable.tag_list).to eq(['awesome', 'epic'])
94
+ expect(@taggable.cached_tag_list).to eq('awesome; epic')
95
+
96
+ @taggable = CachedModel.find_by_name('Bob Jones')
97
+ expect(@taggable.tag_list).to eq(['awesome', 'epic'])
98
+ expect(@taggable.cached_tag_list).to eq('awesome; epic')
99
+ end
100
+ end
101
+
80
102
  describe 'CachingWithArray' do
81
103
  pending '#TODO'
82
104
  end
@@ -83,6 +83,18 @@ describe ActsAsTaggableOn::TagList do
83
83
  new_tag_list = tag_list.concat(another_tag_list)
84
84
  expect(new_tag_list.class).to eq(ActsAsTaggableOn::TagList)
85
85
  end
86
+
87
+ context 'without duplicates' do
88
+ let(:arr) { ['crazy', 'alien'] }
89
+ let(:another_tag_list) { ActsAsTaggableOn::TagList.new(*arr) }
90
+ it 'adds other list' do
91
+ expect(tag_list.concat(another_tag_list)).to eq(%w[awesome radical crazy alien])
92
+ end
93
+
94
+ it 'adds other array' do
95
+ expect(tag_list.concat(arr)).to eq(%w[awesome radical crazy alien])
96
+ end
97
+ end
86
98
  end
87
99
 
88
100
  describe '#to_s' do
@@ -92,7 +104,7 @@ describe ActsAsTaggableOn::TagList do
92
104
 
93
105
  it 'should be able to call to_s on a frozen tag list' do
94
106
  tag_list.freeze
95
- expect(-> { tag_list.add('cool', 'rad,bodacious') }).to raise_error
107
+ expect(-> { tag_list.add('cool', 'rad,bodacious') }).to raise_error(RuntimeError)
96
108
  expect(-> { tag_list.to_s }).to_not raise_error
97
109
  end
98
110
  end
@@ -114,6 +126,20 @@ describe ActsAsTaggableOn::TagList do
114
126
 
115
127
  ActsAsTaggableOn.force_lowercase = false
116
128
  end
129
+
130
+ it 'should ignore case when removing duplicates if strict_case_match is false' do
131
+ tag_list = ActsAsTaggableOn::TagList.new('Junglist', 'JUNGLIST', 'Junglist', 'Massive', 'MASSIVE', 'MASSIVE')
132
+
133
+ expect(tag_list.to_s).to eq('Junglist, Massive')
134
+ end
135
+
136
+ it 'should not ignore case when removing duplicates if strict_case_match is true' do
137
+ ActsAsTaggableOn.strict_case_match = true
138
+ tag_list = ActsAsTaggableOn::TagList.new('Junglist', 'JUNGLIST', 'Junglist', 'Massive', 'MASSIVE', 'MASSIVE')
139
+
140
+ expect(tag_list.to_s).to eq('Junglist, JUNGLIST, Massive, MASSIVE')
141
+ ActsAsTaggableOn.strict_case_match = false
142
+ end
117
143
  end
118
144
 
119
145
  describe 'custom parser' do
@@ -55,6 +55,21 @@ describe ActsAsTaggableOn::Tag do
55
55
  end
56
56
  end
57
57
 
58
+ describe 'for context' do
59
+ before(:each) do
60
+ @user.skill_list.add('ruby')
61
+ @user.save
62
+ end
63
+
64
+ it 'should return tags that have been used in the given context' do
65
+ expect(ActsAsTaggableOn::Tag.for_context('skills').pluck(:name)).to include('ruby')
66
+ end
67
+
68
+ it 'should not return tags that have been used in other contexts' do
69
+ expect(ActsAsTaggableOn::Tag.for_context('needs').pluck(:name)).to_not include('ruby')
70
+ end
71
+ end
72
+
58
73
  describe 'find or create by name' do
59
74
  before(:each) do
60
75
  @tag.name = 'awesome'
@@ -119,6 +119,21 @@ describe 'Taggable' do
119
119
  expect(@taggable.tag_counts_on(:tags).length).to eq(2)
120
120
  end
121
121
 
122
+ context 'tag_counts on a collection' do
123
+ context 'a select clause is specified on the collection' do
124
+ it 'should return tag counts without raising an error' do
125
+ expect(TaggableModel.tag_counts_on(:tags)).to be_empty
126
+
127
+ @taggable.tag_list = %w(awesome epic)
128
+ @taggable.save
129
+
130
+ expect {
131
+ expect(TaggableModel.select(:name).tag_counts_on(:tags).length).to eq(2)
132
+ }.not_to raise_error
133
+ end
134
+ end
135
+ end
136
+
122
137
  it 'should have tags_on' do
123
138
  expect(TaggableModel.tags_on(:tags)).to be_empty
124
139
 
@@ -226,8 +241,10 @@ describe 'Taggable' do
226
241
  it "should be able to find a tag using dates" do
227
242
  @taggable.skill_list = "ruby"
228
243
  @taggable.save
244
+ today = Date.today.to_time.utc
245
+ tomorrow = Date.tomorrow.to_time.utc
229
246
 
230
- expect(TaggableModel.tagged_with("ruby", :start_at => Date.today, :end_at => Date.tomorrow).count).to eq(1)
247
+ expect(TaggableModel.tagged_with("ruby", :start_at => today, :end_at => tomorrow).count).to eq(1)
231
248
  end
232
249
 
233
250
  it "shouldn't be able to find a tag outside date range" do
@@ -380,7 +397,6 @@ describe 'Taggable' do
380
397
  # Test specific join syntaxes:
381
398
  frank.untaggable_models.create!
382
399
  expect(TaggableModel.tagged_with('rails').joins(:untaggable_models).all_tag_counts.size).to eq(2)
383
- expect(TaggableModel.tagged_with('rails').joins(untaggable_models: :taggable_model).all_tag_counts.size).to eq(2)
384
400
  expect(TaggableModel.tagged_with('rails').joins([:untaggable_models]).all_tag_counts.size).to eq(2)
385
401
  end
386
402
 
@@ -395,7 +411,6 @@ describe 'Taggable' do
395
411
  # Test specific join syntaxes:
396
412
  frank.untaggable_models.create!
397
413
  expect(TaggableModel.tagged_with('rails').joins(:untaggable_models).all_tags.size).to eq(2)
398
- expect(TaggableModel.tagged_with('rails').joins(untaggable_models: :taggable_model).all_tags.size).to eq(2)
399
414
  expect(TaggableModel.tagged_with('rails').joins([:untaggable_models]).all_tags.size).to eq(2)
400
415
  end
401
416
 
@@ -459,7 +474,7 @@ describe 'Taggable' do
459
474
 
460
475
  expect(TaggableModel.tagged_with(%w(bob tricia), wild: true, any: true).to_a.sort_by { |o| o.id }).to eq([bob, frank, steve])
461
476
  expect(TaggableModel.tagged_with(%w(bob tricia), wild: true, exclude: true).to_a).to eq([jim])
462
- expect(TaggableModel.tagged_with('ji', wild: true, any: true).to_a).to eq([frank, jim])
477
+ expect(TaggableModel.tagged_with('ji', wild: true, any: true).to_a =~ [frank, jim])
463
478
  end
464
479
  end
465
480
 
@@ -743,7 +758,6 @@ describe 'Taggable' do
743
758
 
744
759
  context 'Model.limit(x).tag_counts.sum(:tags_count)' do
745
760
  it 'should not break on Mysql' do
746
- # Activerecord 3.2 return a string
747
761
  expect(TaggableModel.limit(2).tag_counts.sum('tags_count').to_i).to eq(5)
748
762
  end
749
763
  end
@@ -49,15 +49,69 @@ describe ActsAsTaggableOn::Tagging do
49
49
  ActsAsTaggableOn.remove_unused_tags = previous_setting
50
50
  end
51
51
 
52
- pending 'context scopes' do
53
- describe '.by_context'
54
-
55
- describe '.by_contexts'
56
-
57
- describe '.owned_by'
58
-
59
- describe '.not_owned'
60
-
52
+ describe 'context scopes' do
53
+ before do
54
+ @tagging_2 = ActsAsTaggableOn::Tagging.new
55
+ @tagging_3 = ActsAsTaggableOn::Tagging.new
56
+
57
+ @tagger = User.new
58
+ @tagger_2 = User.new
59
+
60
+ @tagging.taggable = TaggableModel.create(name: "Black holes")
61
+ @tagging.tag = ActsAsTaggableOn::Tag.create(name: "Physics")
62
+ @tagging.tagger = @tagger
63
+ @tagging.context = 'Science'
64
+ @tagging.save
65
+
66
+ @tagging_2.taggable = TaggableModel.create(name: "Satellites")
67
+ @tagging_2.tag = ActsAsTaggableOn::Tag.create(name: "Technology")
68
+ @tagging_2.tagger = @tagger_2
69
+ @tagging_2.context = 'Science'
70
+ @tagging_2.save
71
+
72
+ @tagging_3.taggable = TaggableModel.create(name: "Satellites")
73
+ @tagging_3.tag = ActsAsTaggableOn::Tag.create(name: "Engineering")
74
+ @tagging_3.tagger = @tagger_2
75
+ @tagging_3.context = 'Astronomy'
76
+ @tagging_3.save
77
+
78
+ end
79
+
80
+ describe '.owned_by' do
81
+ it "should belong to a specific user" do
82
+ expect(ActsAsTaggableOn::Tagging.owned_by(@tagger).first).to eq(@tagging)
83
+ end
84
+ end
85
+
86
+ describe '.by_context' do
87
+ it "should be found by context" do
88
+ expect(ActsAsTaggableOn::Tagging.by_context('Science').length).to eq(2);
89
+ end
90
+ end
91
+
92
+ describe '.by_contexts' do
93
+ it "should find taggings by contexts" do
94
+ expect(ActsAsTaggableOn::Tagging.by_contexts(['Science', 'Astronomy']).first).to eq(@tagging);
95
+ expect(ActsAsTaggableOn::Tagging.by_contexts(['Science', 'Astronomy']).second).to eq(@tagging_2);
96
+ expect(ActsAsTaggableOn::Tagging.by_contexts(['Science', 'Astronomy']).third).to eq(@tagging_3);
97
+ expect(ActsAsTaggableOn::Tagging.by_contexts(['Science', 'Astronomy']).length).to eq(3);
98
+ end
99
+ end
100
+
101
+ describe '.not_owned' do
102
+ before do
103
+ @tagging_4 = ActsAsTaggableOn::Tagging.new
104
+ @tagging_4.taggable = TaggableModel.create(name: "Gravity")
105
+ @tagging_4.tag = ActsAsTaggableOn::Tag.create(name: "Space")
106
+ @tagging_4.context = "Science"
107
+ @tagging_4.save
108
+ end
109
+
110
+ it "should found the taggings that do not have owner" do
111
+ expect(ActsAsTaggableOn::Tagging.all.length).to eq(4)
112
+ expect(ActsAsTaggableOn::Tagging.not_owned.length).to eq(1)
113
+ expect(ActsAsTaggableOn::Tagging.not_owned.first).to eq(@tagging_4)
114
+ end
115
+ end
61
116
  end
62
-
63
117
  end
@@ -7,12 +7,15 @@ ActiveRecord::Schema.define version: 0 do
7
7
  add_index 'tags', ['name'], name: 'index_tags_on_name', unique: true
8
8
 
9
9
  create_table :taggings, force: true do |t|
10
- t.references :tag
10
+ t.integer :tag_id
11
11
 
12
12
  # You should make sure that the column created is
13
13
  # long enough to store the required class names.
14
- t.references :taggable, polymorphic: true
15
- t.references :tagger, polymorphic: true
14
+ t.string :taggable_type
15
+ t.integer :taggable_id
16
+
17
+ t.string :tagger_type
18
+ t.integer :tagger_id
16
19
 
17
20
  # Limit is created to prevent MySQL error on index
18
21
  # length for MyISAM table type: http://bit.ly/vgW2Ql
@@ -23,6 +26,7 @@ ActiveRecord::Schema.define version: 0 do
23
26
  add_index 'taggings',
24
27
  ['tag_id', 'taggable_id', 'taggable_type', 'context', 'tagger_id', 'tagger_type'],
25
28
  unique: true, name: 'taggings_idx'
29
+ add_index 'taggings', :tag_id , name: 'index_taggings_on_tag_id'
26
30
 
27
31
  # above copied from
28
32
  # generators/acts_as_taggable_on/migration/migration_generator
@@ -13,13 +13,7 @@ if File.exist?(database_yml)
13
13
  config = ActiveRecord::Base.configurations[db_name]
14
14
 
15
15
  begin
16
- #activerecord 4 uses symbol
17
- #TODO, remove when activerecord 3 support is dropped
18
- if ActsAsTaggableOn::Utils.active_record4?
19
- ActiveRecord::Base.establish_connection(db_name.to_sym)
20
- else
21
- ActiveRecord::Base.establish_connection(db_name)
22
- end
16
+ ActiveRecord::Base.establish_connection(db_name.to_sym)
23
17
  ActiveRecord::Base.connection
24
18
  rescue
25
19
  case db_name
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts-as-taggable-on
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.5.0
4
+ version: 4.0.0.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Bleigh
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-03-03 00:00:00.000000000 Z
12
+ date: 2016-07-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -17,20 +17,14 @@ dependencies:
17
17
  requirements:
18
18
  - - ">="
19
19
  - !ruby/object:Gem::Version
20
- version: '3.2'
21
- - - "<"
22
- - !ruby/object:Gem::Version
23
- version: '5'
20
+ version: '4.0'
24
21
  type: :runtime
25
22
  prerelease: false
26
23
  version_requirements: !ruby/object:Gem::Requirement
27
24
  requirements:
28
25
  - - ">="
29
26
  - !ruby/object:Gem::Version
30
- version: '3.2'
31
- - - "<"
32
- - !ruby/object:Gem::Version
33
- version: '5'
27
+ version: '4.0'
34
28
  - !ruby/object:Gem::Dependency
35
29
  name: sqlite3
36
30
  requirement: !ruby/object:Gem::Requirement
@@ -51,14 +45,14 @@ dependencies:
51
45
  requirements:
52
46
  - - "~>"
53
47
  - !ruby/object:Gem::Version
54
- version: 0.3.7
48
+ version: '0.3'
55
49
  type: :development
56
50
  prerelease: false
57
51
  version_requirements: !ruby/object:Gem::Requirement
58
52
  requirements:
59
53
  - - "~>"
60
54
  - !ruby/object:Gem::Version
61
- version: 0.3.7
55
+ version: '0.3'
62
56
  - !ruby/object:Gem::Dependency
63
57
  name: pg
64
58
  requirement: !ruby/object:Gem::Requirement
@@ -170,19 +164,18 @@ files:
170
164
  - db/migrate/3_add_taggings_counter_cache_to_tags.rb
171
165
  - db/migrate/4_add_missing_taggable_index.rb
172
166
  - db/migrate/5_change_collation_for_tag_names.rb
173
- - gemfiles/activerecord_3.2.gemfile
167
+ - db/migrate/6_add_missing_indexes.rb
174
168
  - gemfiles/activerecord_4.0.gemfile
175
169
  - gemfiles/activerecord_4.1.gemfile
176
170
  - gemfiles/activerecord_4.2.gemfile
171
+ - gemfiles/activerecord_5.0.gemfile
177
172
  - lib/acts-as-taggable-on.rb
178
173
  - lib/acts_as_taggable_on.rb
179
- - lib/acts_as_taggable_on/compatibility.rb
180
174
  - lib/acts_as_taggable_on/default_parser.rb
181
175
  - lib/acts_as_taggable_on/engine.rb
182
176
  - lib/acts_as_taggable_on/generic_parser.rb
183
177
  - lib/acts_as_taggable_on/tag.rb
184
178
  - lib/acts_as_taggable_on/tag_list.rb
185
- - lib/acts_as_taggable_on/tag_list_parser.rb
186
179
  - lib/acts_as_taggable_on/taggable.rb
187
180
  - lib/acts_as_taggable_on/taggable/cache.rb
188
181
  - lib/acts_as_taggable_on/taggable/collection.rb
@@ -203,7 +196,6 @@ files:
203
196
  - spec/acts_as_taggable_on/generic_parser_spec.rb
204
197
  - spec/acts_as_taggable_on/related_spec.rb
205
198
  - spec/acts_as_taggable_on/single_table_inheritance_spec.rb
206
- - spec/acts_as_taggable_on/tag_list_parser_spec.rb
207
199
  - spec/acts_as_taggable_on/tag_list_spec.rb
208
200
  - spec/acts_as_taggable_on/tag_spec.rb
209
201
  - spec/acts_as_taggable_on/taggable/dirty_spec.rb
@@ -254,15 +246,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
254
246
  requirements:
255
247
  - - ">="
256
248
  - !ruby/object:Gem::Version
257
- version: 1.9.3
249
+ version: 2.0.0
258
250
  required_rubygems_version: !ruby/object:Gem::Requirement
259
251
  requirements:
260
- - - ">="
252
+ - - ">"
261
253
  - !ruby/object:Gem::Version
262
- version: '0'
254
+ version: 1.3.1
263
255
  requirements: []
264
256
  rubyforge_project:
265
- rubygems_version: 2.4.5
257
+ rubygems_version: 2.4.5.1
266
258
  signing_key:
267
259
  specification_version: 4
268
260
  summary: Advanced tagging for Rails.
@@ -274,7 +266,6 @@ test_files:
274
266
  - spec/acts_as_taggable_on/generic_parser_spec.rb
275
267
  - spec/acts_as_taggable_on/related_spec.rb
276
268
  - spec/acts_as_taggable_on/single_table_inheritance_spec.rb
277
- - spec/acts_as_taggable_on/tag_list_parser_spec.rb
278
269
  - spec/acts_as_taggable_on/tag_list_spec.rb
279
270
  - spec/acts_as_taggable_on/tag_spec.rb
280
271
  - spec/acts_as_taggable_on/taggable/dirty_spec.rb
@@ -1,35 +0,0 @@
1
- module ActsAsTaggableOn::Compatibility
2
- def has_many_with_taggable_compatibility(name, options = {}, &extention)
3
- if ActsAsTaggableOn::Utils.active_record4?
4
- scope, opts = build_taggable_scope_and_options(options)
5
- has_many(name, scope, opts, &extention)
6
- else
7
- has_many(name, options, &extention)
8
- end
9
- end
10
-
11
- def build_taggable_scope_and_options(opts)
12
- scope_opts, opts = parse_taggable_options(opts)
13
-
14
- unless scope_opts.empty?
15
- scope = -> {
16
- scope_opts.inject(self) { |result, hash| result.send(*hash) }
17
- }
18
- return [scope, opts]
19
- end
20
-
21
- [nil, opts]
22
- end
23
-
24
- def parse_taggable_options(opts)
25
- scope_opts = {}
26
- [:order, :having, :select, :group, :limit, :offset, :readonly].each do |o|
27
- scope_opts[o] = opts.delete o if opts[o]
28
- end
29
- scope_opts[:where] = opts.delete :conditions if opts[:conditions]
30
- scope_opts[:joins] = opts.delete :include if opts [:include]
31
- scope_opts[:distinct] = opts.delete :uniq if opts[:uniq]
32
-
33
- [scope_opts, opts]
34
- end
35
- end
@@ -1,21 +0,0 @@
1
- module ActsAsTaggableOn
2
- ##
3
- # Returns a new TagList using the given tag string.
4
- #
5
- # Example:
6
- # tag_list = ActsAsTaggableOn::TagListParser.parse("One , Two, Three")
7
- # tag_list # ["One", "Two", "Three"]
8
- module TagListParser
9
- class << self
10
- ## DEPRECATED
11
- def parse(string)
12
- ActiveRecord::Base.logger.warn <<WARNING
13
- ActsAsTaggableOn::TagListParser.parse is deprecated \
14
- and will be removed from v4.0+, use \
15
- ActsAsTaggableOn::TagListParser.new instead
16
- WARNING
17
- DefaultParser.new(string).parse
18
- end
19
- end
20
- end
21
- end
@@ -1,46 +0,0 @@
1
- # -*- encoding : utf-8 -*-
2
- require 'spec_helper'
3
-
4
- describe ActsAsTaggableOn::TagListParser do
5
- it '#parse should return empty array if empty array is passed' do
6
- expect(ActsAsTaggableOn::TagListParser.parse([])).to be_empty
7
- end
8
-
9
- describe 'Multiple Delimiter' do
10
- before do
11
- @old_delimiter = ActsAsTaggableOn.delimiter
12
- end
13
-
14
- after do
15
- ActsAsTaggableOn.delimiter = @old_delimiter
16
- end
17
-
18
- it 'should separate tags by delimiters' do
19
- ActsAsTaggableOn.delimiter = [',', ' ', '\|']
20
- tag_list = ActsAsTaggableOn::TagListParser.parse('cool, data|I have')
21
- expect(tag_list.to_s).to eq('cool, data, I, have')
22
- end
23
-
24
- it 'should escape quote' do
25
- ActsAsTaggableOn.delimiter = [',', ' ', '\|']
26
- tag_list = ActsAsTaggableOn::TagListParser.parse "'I have'|cool, data"
27
- expect(tag_list.to_s).to eq('"I have", cool, data')
28
-
29
- tag_list = ActsAsTaggableOn::TagListParser.parse '"I, have"|cool, data'
30
- expect(tag_list.to_s).to eq('"I, have", cool, data')
31
- end
32
-
33
- it 'should work for utf8 delimiter and long delimiter' do
34
- ActsAsTaggableOn.delimiter = [',', '的', '可能是']
35
- tag_list = ActsAsTaggableOn::TagListParser.parse('我的东西可能是不见了,还好有备份')
36
- expect(tag_list.to_s).to eq('我, 东西, 不见了, 还好有备份')
37
- end
38
-
39
- it 'should work for multiple quoted tags' do
40
- ActsAsTaggableOn.delimiter = [',']
41
- tag_list = ActsAsTaggableOn::TagListParser.parse('"Ruby Monsters","eat Katzenzungen"')
42
- expect(tag_list.to_s).to eq('Ruby Monsters, eat Katzenzungen')
43
- end
44
- end
45
-
46
- end