acts-as-taggable-on 3.3.0 → 3.4.4

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +13 -16
  3. data/Appraisals +6 -6
  4. data/CHANGELOG.md +103 -4
  5. data/Gemfile +1 -0
  6. data/README.md +63 -2
  7. data/UPGRADING.md +1 -7
  8. data/acts-as-taggable-on.gemspec +2 -2
  9. data/gemfiles/activerecord_3.2.gemfile +2 -1
  10. data/gemfiles/activerecord_4.0.gemfile +2 -1
  11. data/gemfiles/activerecord_4.1.gemfile +2 -1
  12. data/gemfiles/{activerecord_edge.gemfile → activerecord_4.2.gemfile} +3 -2
  13. data/lib/acts-as-taggable-on.rb +15 -2
  14. data/lib/acts_as_taggable_on/default_parser.rb +79 -0
  15. data/lib/acts_as_taggable_on/generic_parser.rb +19 -0
  16. data/lib/acts_as_taggable_on/tag.rb +17 -11
  17. data/lib/acts_as_taggable_on/tag_list.rb +8 -4
  18. data/lib/acts_as_taggable_on/tag_list_parser.rb +7 -64
  19. data/lib/acts_as_taggable_on/taggable/cache.rb +4 -0
  20. data/lib/acts_as_taggable_on/taggable/collection.rb +2 -2
  21. data/lib/acts_as_taggable_on/taggable/core.rb +45 -32
  22. data/lib/acts_as_taggable_on/taggable/ownership.rb +2 -2
  23. data/lib/acts_as_taggable_on/taggable/related.rb +1 -1
  24. data/lib/acts_as_taggable_on/tagging.rb +6 -2
  25. data/lib/acts_as_taggable_on/utils.rb +1 -1
  26. data/lib/acts_as_taggable_on/version.rb +1 -1
  27. data/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb +16 -0
  28. data/spec/acts_as_taggable_on/caching_spec.rb +6 -0
  29. data/spec/acts_as_taggable_on/default_parser_spec.rb +47 -0
  30. data/spec/acts_as_taggable_on/generic_parser_spec.rb +14 -0
  31. data/spec/acts_as_taggable_on/related_spec.rb +9 -0
  32. data/spec/acts_as_taggable_on/tag_list_spec.rb +29 -0
  33. data/spec/acts_as_taggable_on/tag_spec.rb +35 -1
  34. data/spec/acts_as_taggable_on/taggable_spec.rb +2 -1
  35. data/spec/acts_as_taggable_on/tagger_spec.rb +13 -0
  36. data/spec/acts_as_taggable_on/utils_spec.rb +7 -0
  37. data/spec/spec_helper.rb +4 -0
  38. metadata +16 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5c20928991764b079db87d3d1ba32846d0a3e01f
4
- data.tar.gz: 94cae20632e6d61d21cd55921cb7ee284cb6f766
3
+ metadata.gz: b3150df9e4bb27c039d1bf451b14848f05867cd1
4
+ data.tar.gz: 9451664d7c39a2bae61c254f8852b7c65101658c
5
5
  SHA512:
6
- metadata.gz: 29cfdac7542aed8bb4f8f55a0c7d33f592739ae1f887a5399e0bd34fd686a5824b3e5335f5037a0ada5928001b4a8b3ca124d21771d5af648fc6f55735bf31da
7
- data.tar.gz: 535aa2433b00889491d6aaf7f488b372ebc1ac2e60f8d9cd2337ae07a19ce2ce1bce3438a1f2db48c77b52a3a57c56648c8c31ddf1b4f0c2447bebae27d67fe0
6
+ metadata.gz: 33408ad30bec8845467d740606689fff474a35ff5440ed15a5320ff2b3a56f2076d557f111409c788c2431f6dfb732a2713b0847880895ed6d5abf7aa86d4bc9
7
+ data.tar.gz: 402c76125e5b27adbf531c9aeccf971af256b2b4545d92daa31b98a25beb3381820055075b6ae73e03efb7dd1c22495ae737655623b536c4703e7929002b624b
data/.travis.yml CHANGED
@@ -1,9 +1,11 @@
1
+ language: ruby
2
+
1
3
  rvm:
2
- - 1.9.3
4
+ - 2.1
5
+ - 2.2
3
6
  - 2.0.0
4
- - 2.1.1
7
+ - 1.9.3
5
8
  - rbx-2
6
- - ruby-head
7
9
 
8
10
  env:
9
11
  - DB=sqlite3
@@ -14,30 +16,25 @@ gemfile:
14
16
  - gemfiles/activerecord_3.2.gemfile
15
17
  - gemfiles/activerecord_4.0.gemfile
16
18
  - gemfiles/activerecord_4.1.gemfile
17
- - gemfiles/activerecord_edge.gemfile
18
19
 
19
- cache: bundler
20
+ sudo: false
21
+
22
+ bundler_args: '--without local_development --jobs 3 --retry 3'
23
+
20
24
  script: bundle exec rake
21
- before_install: gem install bundler
22
- bundler_args: '--without local_development'
25
+
23
26
  matrix:
24
27
  fast_finish: true
25
28
  allow_failures:
26
29
  - gemfile: gemfiles/activerecord_edge.gemfile
27
30
  - rvm: rbx-2
28
- - rvm: ruby-head
29
31
  exclude:
32
+ - rvm: 2.2
33
+ gemfile: gemfiles/activerecord_3.2.gemfile
30
34
  - rvm: 1.9.3
31
35
  gemfile: gemfiles/activerecord_4.0.gemfile
32
36
  - rvm: 1.9.3
33
37
  gemfile: gemfiles/activerecord_4.1.gemfile
34
- - rvm: 1.9.3
35
- gemfile: gemfiles/activerecord_edge.gemfile
36
38
  - rvm: rbx-2
37
39
  gemfile: gemfiles/activerecord_3.2.gemfile
38
- - rvm: ruby-head
39
- gemfile: gemfiles/activerecord_3.2.gemfile
40
- - rvm: ruby-head
41
- gemfile: gemfiles/activerecord_4.0.gemfile
42
- - rvm: ruby-head
43
- gemfile: gemfiles/activerecord_4.1.gemfile
40
+
data/Appraisals CHANGED
@@ -1,16 +1,16 @@
1
1
  appraise "activerecord-3.2" do
2
- gem "activerecord", "~> 3.2"
2
+ gem "activerecord", github: "rails/rails" , branch: '3-2-stable'
3
3
  end
4
4
 
5
5
  appraise "activerecord-4.0" do
6
- gem "activerecord", "~> 4.0"
6
+ gem "activerecord", github: "rails/rails" , branch: '4-0-stable'
7
7
  end
8
8
 
9
9
  appraise "activerecord-4.1" do
10
- gem "activerecord", "~> 4.1"
10
+ gem "activerecord", github: "rails/rails" , branch: '4-1-stable'
11
11
  end
12
12
 
13
- appraise "activerecord-edge" do
14
- gem "activerecord", github: "rails/rails"
15
- gem 'arel', github: 'rails/arel'
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'
16
16
  end
data/CHANGELOG.md CHANGED
@@ -4,18 +4,117 @@ 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
- ### Master [changes](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.2.0...master)
7
+ ### Master [changes](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.4.4...master)
8
8
 
9
9
  * Breaking Changes
10
- * Taggable models are not extend with ActsAsTaggableOn::Utils anymore
11
10
  * Features
12
11
  * Fixes
13
12
  * Performance
14
13
  * Misc
15
- * Deleted outdated benchmark script
16
14
 
15
+ ### [3.4.4 / 2015-02-11](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.4.3...v3.4.4)
17
16
 
18
- ### [3.2.0 / 2014-05-1](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.1.1...v3.2.0)
17
+ * Fixes
18
+ * [@d4rky-pl Add context constraint to find_related_* methods](https://github.com/mbleigh/acts-as-taggable-on/pull/629)
19
+
20
+
21
+ ### [3.4.3 / 2014-09-26](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.4.2...v3.4.3)
22
+
23
+ * Fixes
24
+ * [@warp clears column cache on reset_column_information resolves](https://github.com/mbleigh/acts-as-taggable-on/pull/621)
25
+
26
+ ### [3.4.2 / 2014-09-26](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.4.1...v3.4.2)
27
+
28
+ * Fixes
29
+ * [@stiff fixed tagged_with :any in postgresql](https://github.com/mbleigh/acts-as-taggable-on/pull/570)
30
+ * [@jerefrer fixed encoding in mysql](https://github.com/mbleigh/acts-as-taggable-on/pull/588)
31
+ * [@markedmondson Ensure taggings context aliases are maintained when joining multiple taggables](https://github.com/mbleigh/acts-as-taggable-on/pull/589)
32
+
33
+ ### [3.4.1 / 2014-09-01](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.4.0...v3.4.1)
34
+ * Fixes
35
+ * [@konukhov fix owned ordered taggable bug](https://github.com/mbleigh/acts-as-taggable-on/pull/585)
36
+
37
+ ### [3.4.0 / 2014-08-29](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.3.0...v3.4.0)
38
+
39
+ * Features
40
+ * [@ProGM Support for custom parsers for tags](https://github.com/mbleigh/acts-as-taggable-on/pull/579)
41
+ * [@damzcodes #577 Popular feature](https://github.com/mbleigh/acts-as-taggable-on/pull/577)
42
+ * Fixes
43
+ * [@twalpole Update for rails edge (4.2)](https://github.com/mbleigh/acts-as-taggable-on/pull/583)
44
+ * Performance
45
+ * [@dontfidget #587 Use pluck instead of select](https://github.com/mbleigh/acts-as-taggable-on/pull/587)
46
+
47
+ ### [3.3.0 / 2014-07-08](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.2.6...v3.3.0)
48
+
49
+ * Features
50
+ * [@felipeclopes #488 Support for `start_at` and `end_at` restrictions when selecting tags](https://github.com/mbleigh/acts-as-taggable-on/pull/488)
51
+
52
+ * Fixes
53
+ * [@tonytonyjan #560 Fix for `ActsAsTaggableOn.remove_unused_tags` doesn't work](https://github.com/mbleigh/acts-as-taggable-on/pull/560)
54
+ * [@ThearkInn #555 Fix for `tag_cloud` helper to generate correct css tags](https://github.com/mbleigh/acts-as-taggable-on/pull/555)
55
+
56
+ * Performance
57
+ * [@pcai #556 Add back taggables index in the taggins table](https://github.com/mbleigh/acts-as-taggable-on/pull/556)
58
+
59
+
60
+ ### [3.2.6 / 2014-05-28](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.2.5...v3.2.6)
61
+
62
+ * Fixes
63
+ * [@seuros #548 Fix dirty marking when tags are not ordered](https://github.com/mbleigh/acts-as-taggable-on/issues/548)
64
+
65
+ * Misc
66
+ * [@seuros Remove actionpack dependency](https://github.com/mbleigh/acts-as-taggable-on/commit/5d20e0486c892fbe21af42fdcd79d0b6ebe87ed4)
67
+ * [@seuros #547 Add tests for update_attributes](https://github.com/mbleigh/acts-as-taggable-on/issues/547)
68
+
69
+
70
+ ### [3.2.5 / 2014-05-25](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.2.4...v3.2.5)
71
+
72
+ * Fixes
73
+ * [@seuros #546 Fix autoload bug. Now require engine file instead of autoloading it](https://github.com/mbleigh/acts-as-taggable-on/issues/546)
74
+
75
+
76
+ ### [3.2.4 / 2014-05-24](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.2.3...v3.2.4)
77
+
78
+ * Fixes
79
+ * [@seuros #544 Fix incorrect query generation related to `GROUP BY` SQL statement](https://github.com/mbleigh/acts-as-taggable-on/issues/544)
80
+
81
+ * Misc
82
+ * [@seuros #545 Remove `ammeter` development dependency](https://github.com/mbleigh/acts-as-taggable-on/pull/545)
83
+ * [@seuros #545 Deprecate `TagList.from` in favor of `TagListParser.parse`](https://github.com/mbleigh/acts-as-taggable-on/pull/545)
84
+ * [@seuros #543 Introduce lazy loading](https://github.com/mbleigh/acts-as-taggable-on/pull/543)
85
+ * [@seuros #541 Deprecate ActsAsTaggableOn::Utils](https://github.com/mbleigh/acts-as-taggable-on/pull/541)
86
+
87
+
88
+ ### [3.2.3 / 2014-05-16](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.2.2...v3.2.3)
89
+
90
+ * Fixes
91
+ * [@seuros #540 Fix for tags removal (it was affecting all records with the same tag)](https://github.com/mbleigh/acts-as-taggable-on/pull/540)
92
+ * [@akcho8 #535 Fix for `options` Hash passed to methods from being deleted by those methods](https://github.com/mbleigh/acts-as-taggable-on/pull/535)
93
+
94
+
95
+ ### [3.2.2 / 2014-05-07](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.2.1...v3.2.2)
96
+
97
+ * Breaking Changes
98
+ * [@seuros #526 Taggable models are not extended with ActsAsTaggableOn::Utils anymore](https://github.com/mbleigh/acts-as-taggable-on/pull/526)
99
+
100
+ * Fixes
101
+ * [@seuros #536 Add explicit conversion of tags to strings (when assigning tags)](https://github.com/mbleigh/acts-as-taggable-on/pull/536)
102
+
103
+ * Misc
104
+ * [@seuros #526 Delete outdated benchmark script](https://github.com/mbleigh/acts-as-taggable-on/pull/526)
105
+ * [@seuros #525 Fix tests so that they pass with MySQL](https://github.com/mbleigh/acts-as-taggable-on/pull/525)
106
+
107
+
108
+ ### [3.2.1 / 2014-05-06](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.2.0...v3.2.1)
109
+
110
+ * Misc
111
+ * [@seuros #523 Run tests loading only ActiveRecord (without the full Rails stack)](https://github.com/mbleigh/acts-as-taggable-on/pull/523)
112
+ * [@seuros #523 Remove activesupport dependency](https://github.com/mbleigh/acts-as-taggable-on/pull/523)
113
+ * [@seuros #523 Introduce database_cleaner in specs](https://github.com/mbleigh/acts-as-taggable-on/pull/523)
114
+ * [@seuros #520 Tag_list cleanup](https://github.com/mbleigh/acts-as-taggable-on/pull/520)
115
+
116
+
117
+ ### [3.2.0 / 2014-05-01](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.1.1...v3.2.0)
19
118
 
20
119
  * Breaking Changes
21
120
  * ActsAsTaggableOn::Tag is not extend with ActsAsTaggableOn::Utils anymore
data/Gemfile CHANGED
@@ -7,4 +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
11
  end
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  # ActsAsTaggableOn
2
+ [![Gem Version](https://badge.fury.io/rb/acts-as-taggable-on.svg)](http://badge.fury.io/rb/acts-as-taggable-on)
2
3
  [![Build Status](https://secure.travis-ci.org/mbleigh/acts-as-taggable-on.png)](http://travis-ci.org/mbleigh/acts-as-taggable-on)
3
4
  [![Code Climate](https://codeclimate.com/github/mbleigh/acts-as-taggable-on.png)](https://codeclimate.com/github/mbleigh/acts-as-taggable-on)
4
5
  [![Inline docs](http://inch-ci.org/github/mbleigh/acts-as-taggable-on.png)](http://inch-ci.org/github/mbleigh/acts-as-taggable-on)
@@ -24,14 +25,14 @@ Versions 2.4.1 and up are compatible with Rails 4 too (thanks to arabonradar and
24
25
 
25
26
  Versions >= 3.x are compatible with Ruby 1.9.3+ and Rails 3 and 4.
26
27
 
27
- For an up-to-date roadmap, see https://github.com/mbleigh/acts-as-taggable-on/issues/milestones
28
+ For an up-to-date roadmap, see https://github.com/mbleigh/acts-as-taggable-on/milestones
28
29
 
29
30
  ## Installation
30
31
 
31
32
  To use it, add it to your Gemfile:
32
33
 
33
34
  ```ruby
34
- gem 'acts-as-taggable-on'
35
+ gem 'acts-as-taggable-on', '~> 3.4'
35
36
  ```
36
37
 
37
38
  and bundle:
@@ -70,6 +71,12 @@ class User < ActiveRecord::Base
70
71
  acts_as_taggable_on :skills, :interests
71
72
  end
72
73
 
74
+ class UsersController < ApplicationController
75
+ def user_params
76
+ params.require(:user).permit(:name, :tag_list => []) ## Rails 4 strong params usage
77
+ end
78
+ end
79
+
73
80
  @user = User.new(:name => "Bobby")
74
81
  ```
75
82
 
@@ -164,6 +171,22 @@ end
164
171
  @user.tag_list # => ["north", "east", "south", "west"]
165
172
  ```
166
173
 
174
+ ### Finding most or least used tags
175
+
176
+ You can find the most or least used tags by using:
177
+
178
+ ```ruby
179
+ ActsAsTaggableOn::Tag.most_used
180
+ ActsAsTaggableOn::Tag.least_used
181
+ ```
182
+
183
+ You can also filter the results by passing the method a limit, however the default limit is 20.
184
+
185
+ ```ruby
186
+ ActsAsTaggableOn::Tag.most_used(10)
187
+ ActsAsTaggableOn::Tag.least_used(10)
188
+ ```
189
+
167
190
  ### Finding Tagged Objects
168
191
 
169
192
  Acts As Taggable On uses scopes to create an association for tags.
@@ -195,6 +218,7 @@ You can also use `:wild => true` option along with `:any` or `:exclude` option.
195
218
 
196
219
  __Tip:__ `User.tagged_with([])` or `User.tagged_with('')` will return `[]`, an empty set of records.
197
220
 
221
+
198
222
  ### Relationships
199
223
 
200
224
  You can find objects of the same type based on similar tags on certain contexts.
@@ -231,6 +255,43 @@ to allow for dynamic tag contexts (this could be user generated tag contexts!)
231
255
  User.tagged_with("same", :on => :customs) # => [@user]
232
256
  ```
233
257
 
258
+ ### Tag Parsers
259
+
260
+ If you want to change how tags are parsed, you can define a your own implementation:
261
+
262
+ ```ruby
263
+ class MyParser < ActsAsTaggableOn::GenericParser
264
+ def parse
265
+ ActsAsTaggableOn::TagList.new.tap do |tag_list|
266
+ tag_list.add @tag_list.split('|')
267
+ end
268
+ end
269
+ end
270
+ ```
271
+
272
+ Now you can use this parser, passing it as parameter:
273
+
274
+ ```ruby
275
+ @user = User.new(:name => "Bobby")
276
+ @user.tag_list = "east, south"
277
+ @user.tag_list.add("north|west", parser: MyParser)
278
+ @user.tag_list # => ["north", "east", "south", "west"]
279
+
280
+ # Or also:
281
+ @user.tag_list.parser = MyParser
282
+ @user.tag_list.add("north|west")
283
+ @user.tag_list # => ["north", "east", "south", "west"]
284
+ ```
285
+
286
+ Or change it globally:
287
+
288
+ ```ruby
289
+ ActsAsTaggable.default_parser = MyParser
290
+ @user = User.new(:name => "Bobby")
291
+ @user.tag_list = "east|south"
292
+ @user.tag_list # => ["east", "south"]
293
+ ```
294
+
234
295
  ### Tag Ownership
235
296
 
236
297
  Tags can have owners:
data/UPGRADING.md CHANGED
@@ -4,10 +4,4 @@ Re-run the migrations generator
4
4
 
5
5
  rake acts_as_taggable_on_engine:install:migrations
6
6
 
7
- It will create any new migrations and skip existing ones
8
-
9
-
10
- ##Breaking changes:
11
-
12
- - ActsAsTaggableOn::Tag is not extend with ActsAsTaggableOn::Utils anymore.
13
- Please use ActsAsTaggableOn::Utils instead
7
+ It will create any new migrations and skip existing ones
@@ -22,13 +22,13 @@ Gem::Specification.new do |gem|
22
22
  gem.post_install_message = File.read('UPGRADING.md')
23
23
  end
24
24
 
25
- gem.add_runtime_dependency 'activerecord', ['>= 3', '< 5']
25
+ gem.add_runtime_dependency 'activerecord', ['>= 3.2', '< 5']
26
26
 
27
27
  gem.add_development_dependency 'sqlite3'
28
28
  gem.add_development_dependency 'mysql2', '~> 0.3.7'
29
29
  gem.add_development_dependency 'pg'
30
30
 
31
- gem.add_development_dependency 'rspec-rails' , '~> 3.0.0.beta'
31
+ gem.add_development_dependency 'rspec-rails'
32
32
  gem.add_development_dependency 'rspec-its'
33
33
  gem.add_development_dependency 'rspec'
34
34
  gem.add_development_dependency 'barrier'
@@ -2,13 +2,14 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "activerecord", "~> 3.2"
5
+ gem "activerecord", :github => "rails/rails", :branch => "3-2-stable"
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
13
  end
13
14
 
14
15
  gemspec :path => "../"
@@ -2,13 +2,14 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "activerecord", "~> 4.0"
5
+ gem "activerecord", :github => "rails/rails", :branch => "4-0-stable"
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
13
  end
13
14
 
14
15
  gemspec :path => "../"
@@ -2,13 +2,14 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "activerecord", "~> 4.1"
5
+ gem "activerecord", :github => "rails/rails", :branch => "4-1-stable"
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
13
  end
13
14
 
14
15
  gemspec :path => "../"
@@ -2,14 +2,15 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "activerecord", :github => "rails/rails"
6
- gem "arel", :github => "rails/arel"
5
+ gem "railties", :github => "rails/rails", :branch => "4-2-stable"
6
+ gem "activerecord", :github => "rails/rails", :branch => "4-2-stable"
7
7
 
8
8
  group :local_development do
9
9
  gem "guard"
10
10
  gem "guard-rspec"
11
11
  gem "appraisal"
12
12
  gem "rake"
13
+ gem "byebug", :platform => :mri_21
13
14
  end
14
15
 
15
16
  gemspec :path => "../"
@@ -1,7 +1,6 @@
1
1
  require 'active_record'
2
2
  require 'active_record/version'
3
3
  require 'active_support/core_ext/module'
4
- require 'action_view'
5
4
 
6
5
  require_relative 'acts_as_taggable_on/engine' if defined?(Rails)
7
6
 
@@ -12,6 +11,8 @@ module ActsAsTaggableOn
12
11
 
13
12
  autoload :Tag
14
13
  autoload :TagList
14
+ autoload :GenericParser
15
+ autoload :DefaultParser
15
16
  autoload :TagListParser
16
17
  autoload :Taggable
17
18
  autoload :Tagger
@@ -57,7 +58,8 @@ module ActsAsTaggableOn
57
58
 
58
59
  class Configuration
59
60
  attr_accessor :delimiter, :force_lowercase, :force_parameterize,
60
- :strict_case_match, :remove_unused_tags
61
+ :strict_case_match, :remove_unused_tags, :default_parser,
62
+ :tags_counter
61
63
 
62
64
  def initialize
63
65
  @delimiter = ','
@@ -65,6 +67,17 @@ module ActsAsTaggableOn
65
67
  @force_parameterize = false
66
68
  @strict_case_match = false
67
69
  @remove_unused_tags = false
70
+ @tags_counter = true
71
+ @default_parser = DefaultParser
72
+ end
73
+
74
+ def delimiter=(string)
75
+ ActiveRecord::Base.logger.warn <<WARNING
76
+ ActsAsTaggableOn.delimiter is deprecated \
77
+ and will be removed from v4.0+, use \
78
+ a ActsAsTaggableOn.default_parser instead
79
+ WARNING
80
+ @delimiter = string
68
81
  end
69
82
  end
70
83
 
@@ -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
@@ -0,0 +1,19 @@
1
+ module ActsAsTaggableOn
2
+ ##
3
+ # Returns a new TagList using the given tag string.
4
+ #
5
+ # Example:
6
+ # tag_list = ActsAsTaggableOn::GenericParser.new.parse("One , Two, Three")
7
+ # tag_list # ["One", "Two", "Three"]
8
+ class GenericParser
9
+ def initialize(tag_list)
10
+ @tag_list = tag_list
11
+ end
12
+
13
+ def parse
14
+ TagList.new.tap do |tag_list|
15
+ tag_list.add @tag_list.split(',').map(&:strip).reject(&:empty?)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -20,6 +20,8 @@ module ActsAsTaggableOn
20
20
  end
21
21
 
22
22
  ### SCOPES:
23
+ scope :most_used, ->(limit = 20) { order('taggings_count desc').limit(limit) }
24
+ scope :least_used, ->(limit = 20) { order('taggings_count asc').limit(limit) }
23
25
 
24
26
  def self.named(name)
25
27
  if ActsAsTaggableOn.strict_case_match
@@ -30,17 +32,10 @@ module ActsAsTaggableOn
30
32
  end
31
33
 
32
34
  def self.named_any(list)
33
- if ActsAsTaggableOn.strict_case_match
34
- clause = list.map { |tag|
35
- sanitize_sql(["name = #{binary}?", as_8bit_ascii(tag)])
36
- }.join(' OR ')
37
- where(clause)
38
- else
39
- clause = list.map { |tag|
40
- sanitize_sql(['LOWER(name) = LOWER(?)', as_8bit_ascii(unicode_downcase(tag))])
41
- }.join(' OR ')
42
- where(clause)
43
- end
35
+ clause = list.map { |tag|
36
+ sanitize_sql_for_named_any(tag).force_encoding('BINARY')
37
+ }.join(' OR ')
38
+ where(clause)
44
39
  end
45
40
 
46
41
  def self.named_like(name)
@@ -101,6 +96,9 @@ module ActsAsTaggableOn
101
96
  end
102
97
 
103
98
  class << self
99
+
100
+
101
+
104
102
  private
105
103
 
106
104
  def comparable_name(str)
@@ -130,6 +128,14 @@ module ActsAsTaggableOn
130
128
  string.to_s.mb_chars
131
129
  end
132
130
  end
131
+
132
+ def sanitize_sql_for_named_any(tag)
133
+ if ActsAsTaggableOn.strict_case_match
134
+ sanitize_sql(["name = #{binary}?", as_8bit_ascii(tag)])
135
+ else
136
+ sanitize_sql(['LOWER(name) = LOWER(?)', as_8bit_ascii(unicode_downcase(tag))])
137
+ end
138
+ end
133
139
  end
134
140
  end
135
141
  end
@@ -4,8 +4,10 @@ require 'active_support/core_ext/module/delegation'
4
4
  module ActsAsTaggableOn
5
5
  class TagList < Array
6
6
  attr_accessor :owner
7
+ attr_accessor :parser
7
8
 
8
9
  def initialize(*args)
10
+ @parser = ActsAsTaggableOn.default_parser
9
11
  add(*args)
10
12
  end
11
13
 
@@ -88,9 +90,11 @@ module ActsAsTaggableOn
88
90
 
89
91
  def extract_and_apply_options!(args)
90
92
  options = args.last.is_a?(Hash) ? args.pop : {}
91
- options.assert_valid_keys :parse
93
+ options.assert_valid_keys :parse, :parser
92
94
 
93
- args.map! { |a| TagListParser.parse(a) } if options[:parse]
95
+ parser = options[:parser] ? options[:parser] : @parser
96
+
97
+ args.map! { |a| parser.new(a).parse } if options[:parse] || options[:parser]
94
98
 
95
99
  args.flatten!
96
100
  end
@@ -101,9 +105,9 @@ module ActsAsTaggableOn
101
105
  ActiveRecord::Base.logger.warn <<WARNING
102
106
  ActsAsTaggableOn::TagList.from is deprecated \
103
107
  and will be removed from v4.0+, use \
104
- ActsAsTaggableOn::TagListParser.parse instead
108
+ ActsAsTaggableOn::DefaultParser.new instead
105
109
  WARNING
106
- TagListParser.parse(string)
110
+ @parser.new(string).parse
107
111
  end
108
112
 
109
113