acts-as-taggable-on 3.5.0 → 8.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/spec.yml +95 -0
- data/.gitignore +2 -0
- data/Appraisals +12 -9
- data/CHANGELOG.md +212 -70
- data/CONTRIBUTING.md +13 -0
- data/Gemfile +2 -1
- data/README.md +128 -25
- data/acts-as-taggable-on.gemspec +2 -6
- data/db/migrate/1_acts_as_taggable_on_migration.rb +14 -8
- data/db/migrate/2_add_missing_unique_indices.rb +15 -9
- data/db/migrate/3_add_taggings_counter_cache_to_tags.rb +9 -4
- data/db/migrate/4_add_missing_taggable_index.rb +8 -3
- data/db/migrate/5_change_collation_for_tag_names.rb +7 -2
- data/db/migrate/6_add_missing_indexes_on_taggings.rb +22 -0
- data/db/migrate/7_add_tenant_to_taggings.rb +16 -0
- data/gemfiles/activerecord_5.0.gemfile +21 -0
- data/gemfiles/activerecord_5.1.gemfile +21 -0
- data/gemfiles/activerecord_5.2.gemfile +21 -0
- data/gemfiles/activerecord_6.0.gemfile +21 -0
- data/gemfiles/activerecord_6.1.gemfile +23 -0
- data/lib/acts-as-taggable-on.rb +22 -14
- data/lib/acts_as_taggable_on/engine.rb +0 -1
- data/lib/acts_as_taggable_on/tag.rb +27 -23
- data/lib/acts_as_taggable_on/tag_list.rb +3 -13
- data/lib/acts_as_taggable_on/taggable/cache.rb +39 -35
- data/lib/acts_as_taggable_on/taggable/collection.rb +14 -9
- data/lib/acts_as_taggable_on/taggable/core.rb +59 -184
- data/lib/acts_as_taggable_on/taggable/ownership.rb +19 -8
- data/lib/acts_as_taggable_on/taggable/related.rb +1 -1
- data/lib/acts_as_taggable_on/taggable/tag_list_type.rb +4 -0
- data/lib/acts_as_taggable_on/taggable/tagged_with_query/all_tags_query.rb +111 -0
- data/lib/acts_as_taggable_on/taggable/tagged_with_query/any_tags_query.rb +70 -0
- data/lib/acts_as_taggable_on/taggable/tagged_with_query/exclude_tags_query.rb +82 -0
- data/lib/acts_as_taggable_on/taggable/tagged_with_query/query_base.rb +61 -0
- data/lib/acts_as_taggable_on/taggable/tagged_with_query.rb +16 -0
- data/lib/acts_as_taggable_on/taggable.rb +18 -1
- data/lib/acts_as_taggable_on/tagger.rb +12 -11
- data/lib/acts_as_taggable_on/tagging.rb +9 -14
- data/lib/acts_as_taggable_on/utils.rb +4 -5
- data/lib/acts_as_taggable_on/version.rb +1 -2
- data/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb +14 -13
- data/spec/acts_as_taggable_on/acts_as_tagger_spec.rb +1 -1
- data/spec/acts_as_taggable_on/caching_spec.rb +55 -9
- data/spec/acts_as_taggable_on/{taggable/dirty_spec.rb → dirty_spec.rb} +28 -13
- data/spec/acts_as_taggable_on/single_table_inheritance_spec.rb +28 -8
- data/spec/acts_as_taggable_on/tag_list_spec.rb +27 -1
- data/spec/acts_as_taggable_on/tag_spec.rb +31 -1
- data/spec/acts_as_taggable_on/taggable_spec.rb +40 -19
- data/spec/acts_as_taggable_on/tagger_spec.rb +2 -2
- data/spec/acts_as_taggable_on/tagging_spec.rb +87 -7
- data/spec/internal/app/models/altered_inheriting_taggable_model.rb +2 -0
- data/spec/internal/app/models/cached_model_with_array.rb +6 -0
- data/spec/internal/app/models/columns_override_model.rb +5 -0
- data/spec/internal/app/models/company.rb +1 -1
- data/spec/internal/app/models/inheriting_taggable_model.rb +2 -0
- data/spec/internal/app/models/market.rb +1 -1
- data/spec/internal/app/models/non_standard_id_taggable_model.rb +1 -1
- data/spec/internal/app/models/student.rb +2 -0
- data/spec/internal/app/models/taggable_model.rb +3 -0
- data/spec/internal/app/models/user.rb +1 -1
- data/spec/internal/config/database.yml.sample +4 -8
- data/spec/internal/db/schema.rb +23 -7
- data/spec/spec_helper.rb +0 -1
- data/spec/support/database.rb +5 -11
- metadata +27 -75
- data/.travis.yml +0 -40
- data/UPGRADING.md +0 -8
- data/gemfiles/activerecord_3.2.gemfile +0 -15
- data/gemfiles/activerecord_4.0.gemfile +0 -15
- data/gemfiles/activerecord_4.1.gemfile +0 -15
- data/gemfiles/activerecord_4.2.gemfile +0 -16
- data/lib/acts_as_taggable_on/compatibility.rb +0 -35
- data/lib/acts_as_taggable_on/tag_list_parser.rb +0 -21
- data/lib/acts_as_taggable_on/taggable/dirty.rb +0 -36
- data/spec/acts_as_taggable_on/tag_list_parser_spec.rb +0 -46
- data/spec/internal/app/models/models.rb +0 -90
data/README.md
CHANGED
@@ -1,8 +1,41 @@
|
|
1
|
+
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
2
|
+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
3
|
+
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
|
4
|
+
|
5
|
+
- [ActsAsTaggableOn](#actsastaggableon)
|
6
|
+
- [Installation](#installation)
|
7
|
+
- [Post Installation](#post-installation)
|
8
|
+
- [For MySql users](#for-mysql-users)
|
9
|
+
- [Usage](#usage)
|
10
|
+
- [Finding most or least used tags](#finding-most-or-least-used-tags)
|
11
|
+
- [Finding Tagged Objects](#finding-tagged-objects)
|
12
|
+
- [Relationships](#relationships)
|
13
|
+
- [Dynamic Tag Contexts](#dynamic-tag-contexts)
|
14
|
+
- [Tag Parsers](#tag-parsers)
|
15
|
+
- [Tag Ownership](#tag-ownership)
|
16
|
+
- [Working with Owned Tags](#working-with-owned-tags)
|
17
|
+
- [Adding owned tags](#adding-owned-tags)
|
18
|
+
- [Removing owned tags](#removing-owned-tags)
|
19
|
+
- [Dirty objects](#dirty-objects)
|
20
|
+
- [Tag cloud calculations](#tag-cloud-calculations)
|
21
|
+
- [Configuration](#configuration)
|
22
|
+
- [Upgrading](#upgrading)
|
23
|
+
- [Contributors](#contributors)
|
24
|
+
- [Compatibility](#compatibility)
|
25
|
+
- [TODO](#todo)
|
26
|
+
- [Testing](#testing)
|
27
|
+
- [License](#license)
|
28
|
+
|
29
|
+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
30
|
+
|
1
31
|
# ActsAsTaggableOn
|
32
|
+
|
33
|
+
[![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
34
|
[![Gem Version](https://badge.fury.io/rb/acts-as-taggable-on.svg)](http://badge.fury.io/rb/acts-as-taggable-on)
|
3
|
-
[![Build Status](https://
|
4
|
-
[![Code Climate](https://codeclimate.com/github/mbleigh/acts-as-taggable-on.
|
5
|
-
[![Inline docs](http://inch-ci.org/github/mbleigh/acts-as-taggable-on.
|
35
|
+
[![Build Status](https://github.com/mbleigh/acts-as-taggable-on/workflows/spec/badge.svg)](https://github.com/mbleigh/acts-as-taggable-on/actions)
|
36
|
+
[![Code Climate](https://codeclimate.com/github/mbleigh/acts-as-taggable-on.svg)](https://codeclimate.com/github/mbleigh/acts-as-taggable-on)
|
37
|
+
[![Inline docs](http://inch-ci.org/github/mbleigh/acts-as-taggable-on.svg)](http://inch-ci.org/github/mbleigh/acts-as-taggable-on)
|
38
|
+
[![Security](https://hakiri.io/github/mbleigh/acts-as-taggable-on/master.svg)](https://hakiri.io/github/mbleigh/acts-as-taggable-on/master)
|
6
39
|
|
7
40
|
This plugin was originally based on Acts as Taggable on Steroids by Jonathan Viney.
|
8
41
|
It has evolved substantially since that point, but all credit goes to him for the
|
@@ -17,22 +50,14 @@ Enter Acts as Taggable On. Rather than tying functionality to a specific keyword
|
|
17
50
|
tag "contexts" that can be used locally or in combination in the same way steroids
|
18
51
|
was used.
|
19
52
|
|
20
|
-
## Compatibility
|
21
|
-
|
22
|
-
Versions 2.x are compatible with Ruby 1.8.7+ and Rails 3.
|
23
|
-
|
24
|
-
Versions 2.4.1 and up are compatible with Rails 4 too (thanks to arabonradar and cwoodcox).
|
25
|
-
|
26
|
-
Versions >= 3.x are compatible with Ruby 1.9.3+ and Rails 3 and 4.
|
27
53
|
|
28
|
-
For an up-to-date roadmap, see https://github.com/mbleigh/acts-as-taggable-on/milestones
|
29
54
|
|
30
55
|
## Installation
|
31
56
|
|
32
57
|
To use it, add it to your Gemfile:
|
33
58
|
|
34
59
|
```ruby
|
35
|
-
gem 'acts-as-taggable-on', '~>
|
60
|
+
gem 'acts-as-taggable-on', '~> 7.0'
|
36
61
|
```
|
37
62
|
|
38
63
|
and bundle:
|
@@ -48,8 +73,6 @@ Install migrations
|
|
48
73
|
```shell
|
49
74
|
# For the latest versions :
|
50
75
|
rake acts_as_taggable_on_engine:install:migrations
|
51
|
-
# For versions 2.4.1 and earlier :
|
52
|
-
rails generate acts_as_taggable_on:migration
|
53
76
|
```
|
54
77
|
|
55
78
|
Review the generated migrations then migrate :
|
@@ -57,6 +80,8 @@ Review the generated migrations then migrate :
|
|
57
80
|
rake db:migrate
|
58
81
|
```
|
59
82
|
|
83
|
+
If you do not wish or need to support multi-tenancy, the migration for `add_tenant_to_taggings` is optional and can be discarded safely.
|
84
|
+
|
60
85
|
#### For MySql users
|
61
86
|
You can circumvent at any time the problem of special characters [issue 623](https://github.com/mbleigh/acts-as-taggable-on/issues/623) by setting in an initializer file:
|
62
87
|
|
@@ -73,9 +98,6 @@ rake acts_as_taggable_on_engine:tag_names:collate_bin
|
|
73
98
|
See the Configuration section for more details, and a general note valid for older
|
74
99
|
version of the gem.
|
75
100
|
|
76
|
-
#### Upgrading
|
77
|
-
|
78
|
-
see [UPGRADING](UPGRADING.md)
|
79
101
|
|
80
102
|
## Usage
|
81
103
|
|
@@ -83,13 +105,13 @@ Setup
|
|
83
105
|
|
84
106
|
```ruby
|
85
107
|
class User < ActiveRecord::Base
|
86
|
-
|
87
|
-
acts_as_taggable_on :skills, :interests
|
108
|
+
acts_as_taggable_on :tags
|
109
|
+
acts_as_taggable_on :skills, :interests #You can also configure multiple tag types per model
|
88
110
|
end
|
89
111
|
|
90
112
|
class UsersController < ApplicationController
|
91
113
|
def user_params
|
92
|
-
params.require(:user).permit(:name, :tag_list
|
114
|
+
params.require(:user).permit(:name, :tag_list) ## Rails 4 strong params usage
|
93
115
|
end
|
94
116
|
end
|
95
117
|
|
@@ -101,6 +123,7 @@ Add and remove a single tag
|
|
101
123
|
```ruby
|
102
124
|
@user.tag_list.add("awesome") # add a single tag. alias for <<
|
103
125
|
@user.tag_list.remove("awesome") # remove a single tag
|
126
|
+
@user.save # save to persist tag_list
|
104
127
|
```
|
105
128
|
|
106
129
|
Add and remove multiple tags in an array
|
@@ -108,6 +131,7 @@ Add and remove multiple tags in an array
|
|
108
131
|
```ruby
|
109
132
|
@user.tag_list.add("awesome", "slick")
|
110
133
|
@user.tag_list.remove("awesome", "slick")
|
134
|
+
@user.save
|
111
135
|
```
|
112
136
|
|
113
137
|
You can also add and remove tags in format of String. This would
|
@@ -218,12 +242,13 @@ User.tagged_with("awesome").by_join_date
|
|
218
242
|
User.tagged_with("awesome").by_join_date.paginate(:page => params[:page], :per_page => 20)
|
219
243
|
|
220
244
|
# Find users that matches all given tags:
|
245
|
+
# NOTE: This only matches users that have the exact set of specified tags. If a user has additional tags, they are not returned.
|
221
246
|
User.tagged_with(["awesome", "cool"], :match_all => true)
|
222
247
|
|
223
248
|
# Find users with any of the specified tags:
|
224
249
|
User.tagged_with(["awesome", "cool"], :any => true)
|
225
250
|
|
226
|
-
# Find users that
|
251
|
+
# Find users that have not been tagged with awesome or cool:
|
227
252
|
User.tagged_with(["awesome", "cool"], :exclude => true)
|
228
253
|
|
229
254
|
# Find users with any of the tags based on context:
|
@@ -273,7 +298,7 @@ User.tagged_with("same", :on => :customs) # => [@user]
|
|
273
298
|
|
274
299
|
### Tag Parsers
|
275
300
|
|
276
|
-
If you want to change how tags are parsed, you can define
|
301
|
+
If you want to change how tags are parsed, you can define your own implementation:
|
277
302
|
|
278
303
|
```ruby
|
279
304
|
class MyParser < ActsAsTaggableOn::GenericParser
|
@@ -302,7 +327,7 @@ Now you can use this parser, passing it as parameter:
|
|
302
327
|
Or change it globally:
|
303
328
|
|
304
329
|
```ruby
|
305
|
-
|
330
|
+
ActsAsTaggableOn.default_parser = MyParser
|
306
331
|
@user = User.new(:name => "Bobby")
|
307
332
|
@user.tag_list = "east|south"
|
308
333
|
@user.tag_list # => ["east", "south"]
|
@@ -331,6 +356,63 @@ Photo.tagged_with("paris", :on => :locations, :owned_by => @some_user)
|
|
331
356
|
@some_user.tag(@some_photo, :with => "paris, normandy", :on => :locations, :skip_save => true) #won't save @some_photo object
|
332
357
|
```
|
333
358
|
|
359
|
+
#### Working with Owned Tags
|
360
|
+
Note that `tag_list` only returns tags whose taggings do not have an owner. Continuing from the above example:
|
361
|
+
```ruby
|
362
|
+
@some_photo.tag_list # => []
|
363
|
+
```
|
364
|
+
To retrieve all tags of an object (regardless of ownership) or if only one owner can tag the object, use `all_tags_list`.
|
365
|
+
|
366
|
+
##### Adding owned tags
|
367
|
+
Note that **owned tags** are added all at once, in the form of ***comma seperated tags*** in string.
|
368
|
+
Also, when you try to add **owned tags** again, it simply overwrites the previous set of **owned tags**.
|
369
|
+
So to append tags in previously existing **owned tags** list, go as follows:
|
370
|
+
```ruby
|
371
|
+
def add_owned_tag
|
372
|
+
@some_item = Item.find(params[:id])
|
373
|
+
owned_tag_list = @some_item.all_tags_list - @some_item.tag_list
|
374
|
+
owned_tag_list += [(params[:tag])]
|
375
|
+
@tag_owner.tag(@some_item, :with => stringify(owned_tag_list), :on => :tags)
|
376
|
+
@some_item.save
|
377
|
+
end
|
378
|
+
|
379
|
+
def stringify(tag_list)
|
380
|
+
tag_list.inject('') { |memo, tag| memo += (tag + ',') }[0..-1]
|
381
|
+
end
|
382
|
+
```
|
383
|
+
##### Removing owned tags
|
384
|
+
Similarly as above, removing will be as follows:
|
385
|
+
```ruby
|
386
|
+
def remove_owned_tag
|
387
|
+
@some_item = Item.find(params[:id])
|
388
|
+
owned_tag_list = @some_item.all_tags_list - @some_item.tag_list
|
389
|
+
owned_tag_list -= [(params[:tag])]
|
390
|
+
@tag_owner.tag(@some_item, :with => stringify(owned_tag_list), :on => :tags)
|
391
|
+
@some_item.save
|
392
|
+
end
|
393
|
+
```
|
394
|
+
|
395
|
+
### Tag Tenancy
|
396
|
+
|
397
|
+
Tags support multi-tenancy. This is useful for applications where a Tag belongs to a scoped set of models:
|
398
|
+
|
399
|
+
```ruby
|
400
|
+
class Account < ActiveRecord::Base
|
401
|
+
has_many :photos
|
402
|
+
end
|
403
|
+
|
404
|
+
class User < ActiveRecord::Base
|
405
|
+
belongs_to :account
|
406
|
+
acts_as_taggable_on :tags
|
407
|
+
acts_as_taggable_tenant :account_id
|
408
|
+
end
|
409
|
+
|
410
|
+
@user1.tag_list = ["foo", "bar"] # these taggings will automatically have the tenant saved
|
411
|
+
@user2.tag_list = ["bar", "baz"]
|
412
|
+
|
413
|
+
ActsAsTaggableOn::Tag.for_tenant(@user1.account.id) # returns Tag models for "foo" and "bar", but not "baz"
|
414
|
+
```
|
415
|
+
|
334
416
|
### Dirty objects
|
335
417
|
|
336
418
|
```ruby
|
@@ -429,6 +511,13 @@ If you would like to have an exact match covering special characters with MySql:
|
|
429
511
|
ActsAsTaggableOn.force_binary_collation = true
|
430
512
|
```
|
431
513
|
|
514
|
+
If you would like to specify table names:
|
515
|
+
|
516
|
+
```ruby
|
517
|
+
ActsAsTaggableOn.tags_table = 'aato_tags'
|
518
|
+
ActsAsTaggableOn.taggings_table = 'aato_taggings'
|
519
|
+
```
|
520
|
+
|
432
521
|
If you want to change the default delimiter (it defaults to ','). You can also pass in an array of delimiters such as ([',', '|']):
|
433
522
|
|
434
523
|
```ruby
|
@@ -446,13 +535,27 @@ USE my_wonderful_app_db;
|
|
446
535
|
ALTER TABLE tags MODIFY name VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin;
|
447
536
|
```
|
448
537
|
|
538
|
+
#### Upgrading
|
539
|
+
|
540
|
+
see [UPGRADING](UPGRADING.md)
|
541
|
+
|
449
542
|
## Contributors
|
450
543
|
|
451
544
|
We have a long list of valued contributors. [Check them all](https://github.com/mbleigh/acts-as-taggable-on/contributors)
|
452
545
|
|
453
|
-
##
|
546
|
+
## Compatibility
|
547
|
+
|
548
|
+
Versions 2.x are compatible with Ruby 1.8.7+ and Rails 3.
|
549
|
+
|
550
|
+
Versions 2.4.1 and up are compatible with Rails 4 too (thanks to arabonradar and cwoodcox).
|
551
|
+
|
552
|
+
Versions >= 3.x are compatible with Ruby 1.9.3+ and Rails 3 and 4.
|
454
553
|
|
455
|
-
|
554
|
+
Versions >= 4.x are compatible with Ruby 2.0.0+ and Rails 4 and 5.
|
555
|
+
|
556
|
+
Versions >= 7.x are compatible with Ruby 2.3.7+ and Rails 5 and 6.
|
557
|
+
|
558
|
+
For an up-to-date roadmap, see https://github.com/mbleigh/acts-as-taggable-on/milestones
|
456
559
|
|
457
560
|
## TODO
|
458
561
|
|
data/acts-as-taggable-on.gemspec
CHANGED
@@ -16,17 +16,13 @@ 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 = '>=
|
19
|
+
gem.required_ruby_version = '>= 2.3.7'
|
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',
|
26
|
-
|
27
|
-
gem.add_development_dependency 'sqlite3'
|
28
|
-
gem.add_development_dependency 'mysql2', '~> 0.3.7'
|
29
|
-
gem.add_development_dependency 'pg'
|
25
|
+
gem.add_runtime_dependency 'activerecord', '>= 5.0', '< 6.2'
|
30
26
|
|
31
27
|
gem.add_development_dependency 'rspec-rails'
|
32
28
|
gem.add_development_dependency 'rspec-its'
|
@@ -1,11 +1,17 @@
|
|
1
|
-
|
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
|
2
7
|
def self.up
|
3
|
-
create_table
|
8
|
+
create_table ActsAsTaggableOn.tags_table do |t|
|
4
9
|
t.string :name
|
10
|
+
t.timestamps
|
5
11
|
end
|
6
12
|
|
7
|
-
create_table
|
8
|
-
t.references :tag
|
13
|
+
create_table ActsAsTaggableOn.taggings_table do |t|
|
14
|
+
t.references :tag, foreign_key: { to_table: ActsAsTaggableOn.tags_table }
|
9
15
|
|
10
16
|
# You should make sure that the column created is
|
11
17
|
# long enough to store the required class names.
|
@@ -19,12 +25,12 @@ class ActsAsTaggableOnMigration < ActiveRecord::Migration
|
|
19
25
|
t.datetime :created_at
|
20
26
|
end
|
21
27
|
|
22
|
-
add_index
|
23
|
-
add_index
|
28
|
+
add_index ActsAsTaggableOn.taggings_table, :tag_id
|
29
|
+
add_index ActsAsTaggableOn.taggings_table, [:taggable_id, :taggable_type, :context], name: 'taggings_taggable_context_idx'
|
24
30
|
end
|
25
31
|
|
26
32
|
def self.down
|
27
|
-
drop_table
|
28
|
-
drop_table
|
33
|
+
drop_table ActsAsTaggableOn.taggings_table
|
34
|
+
drop_table ActsAsTaggableOn.tags_table
|
29
35
|
end
|
30
36
|
end
|
@@ -1,19 +1,25 @@
|
|
1
|
-
|
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
|
2
7
|
def self.up
|
3
|
-
add_index
|
8
|
+
add_index ActsAsTaggableOn.tags_table, :name, unique: true
|
4
9
|
|
5
|
-
remove_index :
|
6
|
-
remove_index
|
7
|
-
add_index
|
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,
|
8
13
|
[:tag_id, :taggable_id, :taggable_type, :context, :tagger_id, :tagger_type],
|
9
14
|
unique: true, name: 'taggings_idx'
|
10
15
|
end
|
11
16
|
|
12
17
|
def self.down
|
13
|
-
remove_index
|
18
|
+
remove_index ActsAsTaggableOn.tags_table, :name
|
19
|
+
|
20
|
+
remove_index ActsAsTaggableOn.taggings_table, name: 'taggings_idx'
|
14
21
|
|
15
|
-
|
16
|
-
add_index :
|
17
|
-
add_index :taggings, [:taggable_id, :taggable_type, :context]
|
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'
|
18
24
|
end
|
19
25
|
end
|
@@ -1,14 +1,19 @@
|
|
1
|
-
|
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
|
2
7
|
def self.up
|
3
|
-
add_column
|
8
|
+
add_column ActsAsTaggableOn.tags_table, :taggings_count, :integer, default: 0
|
4
9
|
|
5
10
|
ActsAsTaggableOn::Tag.reset_column_information
|
6
11
|
ActsAsTaggableOn::Tag.find_each do |tag|
|
7
|
-
ActsAsTaggableOn::Tag.reset_counters(tag.id,
|
12
|
+
ActsAsTaggableOn::Tag.reset_counters(tag.id, ActsAsTaggableOn.taggings_table)
|
8
13
|
end
|
9
14
|
end
|
10
15
|
|
11
16
|
def self.down
|
12
|
-
remove_column
|
17
|
+
remove_column ActsAsTaggableOn.tags_table, :taggings_count
|
13
18
|
end
|
14
19
|
end
|
@@ -1,9 +1,14 @@
|
|
1
|
-
|
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
|
2
7
|
def self.up
|
3
|
-
add_index
|
8
|
+
add_index ActsAsTaggableOn.taggings_table, [:taggable_id, :taggable_type, :context], name: 'taggings_taggable_context_idx'
|
4
9
|
end
|
5
10
|
|
6
11
|
def self.down
|
7
|
-
remove_index
|
12
|
+
remove_index ActsAsTaggableOn.taggings_table, name: 'taggings_taggable_context_idx'
|
8
13
|
end
|
9
14
|
end
|
@@ -1,9 +1,14 @@
|
|
1
1
|
# This migration is added to circumvent issue #623 and have special characters
|
2
2
|
# work properly
|
3
|
-
|
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
|
4
9
|
def up
|
5
10
|
if ActsAsTaggableOn::Utils.using_mysql?
|
6
|
-
execute("ALTER TABLE
|
11
|
+
execute("ALTER TABLE #{ActsAsTaggableOn.tags_table} MODIFY name varchar(255) CHARACTER SET utf8 COLLATE utf8_bin;")
|
7
12
|
end
|
8
13
|
end
|
9
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,16 @@
|
|
1
|
+
if ActiveRecord.gem_version >= Gem::Version.new('5.0')
|
2
|
+
class AddTenantToTaggings < ActiveRecord::Migration[4.2]; end
|
3
|
+
else
|
4
|
+
class AddTenantToTaggings < ActiveRecord::Migration; end
|
5
|
+
end
|
6
|
+
AddTenantToTaggings.class_eval do
|
7
|
+
def self.up
|
8
|
+
add_column :taggings, :tenant, :string, limit: 128
|
9
|
+
add_index :taggings, :tenant unless index_exists? :taggings, :tenant
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.down
|
13
|
+
remove_index :taggings, :tenant
|
14
|
+
remove_column :taggings, :tenant
|
15
|
+
end
|
16
|
+
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.4'
|
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,23 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "activerecord", "~> 6.1.0"
|
6
|
+
case ENV["DB"]
|
7
|
+
when "postgresql"
|
8
|
+
gem 'pg'
|
9
|
+
when "mysql"
|
10
|
+
gem 'mysql2', '~> 0.5'
|
11
|
+
else
|
12
|
+
gem 'sqlite3'
|
13
|
+
end
|
14
|
+
|
15
|
+
group :local_development do
|
16
|
+
gem "guard"
|
17
|
+
gem "guard-rspec"
|
18
|
+
gem "appraisal"
|
19
|
+
gem "rake"
|
20
|
+
gem "byebug", platforms: [:mri]
|
21
|
+
end
|
22
|
+
|
23
|
+
gemspec path: "../"
|
data/lib/acts-as-taggable-on.rb
CHANGED
@@ -2,7 +2,12 @@ require 'active_record'
|
|
2
2
|
require 'active_record/version'
|
3
3
|
require 'active_support/core_ext/module'
|
4
4
|
|
5
|
-
|
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
|
@@ -27,6 +31,7 @@ module ActsAsTaggableOn
|
|
27
31
|
autoload :Dirty
|
28
32
|
autoload :Ownership
|
29
33
|
autoload :Related
|
34
|
+
autoload :TagListType
|
30
35
|
end
|
31
36
|
|
32
37
|
autoload :Utils
|
@@ -53,13 +58,15 @@ module ActsAsTaggableOn
|
|
53
58
|
def self.glue
|
54
59
|
setting = @configuration.delimiter
|
55
60
|
delimiter = setting.kind_of?(Array) ? setting[0] : setting
|
56
|
-
delimiter.
|
61
|
+
delimiter.end_with?(' ') ? delimiter : "#{delimiter} "
|
57
62
|
end
|
58
63
|
|
59
64
|
class Configuration
|
60
|
-
attr_accessor :
|
61
|
-
:
|
62
|
-
:tags_counter
|
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
|
63
70
|
|
64
71
|
def initialize
|
65
72
|
@delimiter = ','
|
@@ -70,12 +77,12 @@ module ActsAsTaggableOn
|
|
70
77
|
@tags_counter = true
|
71
78
|
@default_parser = DefaultParser
|
72
79
|
@force_binary_collation = false
|
80
|
+
@tags_table = :tags
|
81
|
+
@taggings_table = :taggings
|
73
82
|
end
|
74
83
|
|
75
84
|
def strict_case_match=(force_cs)
|
76
|
-
|
77
|
-
@strict_case_match = force_cs
|
78
|
-
end
|
85
|
+
@strict_case_match = force_cs unless @force_binary_collation
|
79
86
|
end
|
80
87
|
|
81
88
|
def delimiter=(string)
|
@@ -89,7 +96,7 @@ WARNING
|
|
89
96
|
|
90
97
|
def force_binary_collation=(force_bin)
|
91
98
|
if Utils.using_mysql?
|
92
|
-
if force_bin
|
99
|
+
if force_bin
|
93
100
|
Configuration.apply_binary_collation(true)
|
94
101
|
@force_binary_collation = true
|
95
102
|
@strict_case_match = true
|
@@ -103,10 +110,12 @@ WARNING
|
|
103
110
|
def self.apply_binary_collation(bincoll)
|
104
111
|
if Utils.using_mysql?
|
105
112
|
coll = 'utf8_general_ci'
|
106
|
-
if bincoll
|
107
|
-
|
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."
|
108
118
|
end
|
109
|
-
ActiveRecord::Migration.execute("ALTER TABLE tags MODIFY name varchar(255) CHARACTER SET utf8 COLLATE #{coll};")
|
110
119
|
end
|
111
120
|
end
|
112
121
|
|
@@ -116,7 +125,6 @@ WARNING
|
|
116
125
|
end
|
117
126
|
|
118
127
|
ActiveSupport.on_load(:active_record) do
|
119
|
-
extend ActsAsTaggableOn::Compatibility
|
120
128
|
extend ActsAsTaggableOn::Taggable
|
121
129
|
include ActsAsTaggableOn::Tagger
|
122
130
|
end
|