gutentag 2.5.4 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +11 -0
- data/Gemfile +4 -0
- data/README.md +12 -4
- data/db/migrate/1_gutentag_tables.rb +1 -3
- data/db/migrate/2_gutentag_cache_counter.rb +1 -3
- data/db/migrate/3_no_null_counters.rb +1 -3
- data/gutentag.gemspec +2 -2
- data/lib/gutentag/engine.rb +4 -0
- data/lib/gutentag/generators/migration_versions_generator.rb +48 -0
- data/lib/gutentag/tagged_with/query.rb +10 -2
- data/spec/gutentag/active_record_spec.rb +20 -0
- data/spec/spec_helper.rb +2 -1
- data/spec/support/adjust_migrations.rb +63 -0
- metadata +4 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b49f3b3dd099ef714f2b23fa1d0e1b08059c59c15447cdece6ee07ac1a0a1272
|
4
|
+
data.tar.gz: c0ef3dd657f3c0b6fe216b80807f74bed2abbdefcbd2c6c467176a8ca16b38a2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ffeef43eb46712c0a261fc569db0571cc2ad66b68254cac89afbba58df15b8f41142b9401f170997608d692d81c353b744b1d71756520f7a80e4cb9c84caeb37
|
7
|
+
data.tar.gz: 80996c6d6b7f8addfb86092b80c8ffed4c28f60629db98e126fab4303865b215c4efbf76de30e9d5c8ab74e7a76859fbdfb9fff5d1c16905153f9a91d1aa6e7c
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,17 @@
|
|
2
2
|
|
3
3
|
All notable changes to this project (at least, from v0.5.0 onwards) will be documented in this file.
|
4
4
|
|
5
|
+
## 2.6.0 - 2021-07-10
|
6
|
+
|
7
|
+
### Added
|
8
|
+
|
9
|
+
* Queries can now be made for objects that have _none_ of the specified tags using `:match => :none` ([Rares S](https://github.com/laleshii) in [#79](https://github.com/pat/gutentag/pull/79)).
|
10
|
+
* Added a generator `gutentag:migration_versions` to update generated migrations so they use the current version of Rails/ActiveRecord's Migration superclass. See discussion in [#80](https://github.com/pat/gutentag/issues/80).
|
11
|
+
|
12
|
+
### Changed
|
13
|
+
|
14
|
+
* When adding Gutentag to a new app, the migrations require the `gutentag:migration_versions` generator to be run to ensure the latest ActiveRecord migration superclass is used. This change has no impact to existing apps. See discussion in [#80](https://github.com/pat/gutentag/issues/80).
|
15
|
+
|
5
16
|
## 2.5.4 - 2021-02-21
|
6
17
|
|
7
18
|
### Fixed
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -8,7 +8,7 @@ A good, simple, solid tagging extension for ActiveRecord.
|
|
8
8
|
|
9
9
|
This was initially built partly as a proof-of-concept, partly to see how a tagging gem could work when it's not all stuffed within models, and partly just because I wanted a simpler tagging library. It's now a solid little tagging Rails engine.
|
10
10
|
|
11
|
-
If you want to know more, read [this blog post](http://freelancing-gods.com/posts/gutentag_simple_rails_tagging).
|
11
|
+
If you want to know more, read [this blog post](http://freelancing-gods.com/posts/gutentag_simple_rails_tagging), or have a look at [the Examples page](https://github.com/pat/gutentag/wiki/Examples) in the wiki (which includes a starting point for accepting tag values in a form).
|
12
12
|
|
13
13
|
## Contents
|
14
14
|
|
@@ -67,6 +67,13 @@ To return records that have _all_ specified tags, use `:match => :all`:
|
|
67
67
|
Article.tagged_with(:ids => [tag_a.id, tag_b.id], :match => :all)
|
68
68
|
```
|
69
69
|
|
70
|
+
To return records that have _none_ of the specified tags, use `:match => :none`:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
# Returns all articles that have *neither* tag_a nor tag_b.
|
74
|
+
Article.tagged_with(:ids => [tag_a.id, tag_b.id], :match => :none)
|
75
|
+
```
|
76
|
+
|
70
77
|
<h2 id="installation">Installation</h2>
|
71
78
|
|
72
79
|
### Dependencies
|
@@ -86,11 +93,12 @@ Get it into your Gemfile - and don't forget the version constraint!
|
|
86
93
|
gem 'gutentag', '~> 2.5'
|
87
94
|
```
|
88
95
|
|
89
|
-
Next: your tags get persisted to your database, so let's import
|
96
|
+
Next: your tags get persisted to your database, so let's import the migrations, update them to your current version of Rails, and then migrate:
|
90
97
|
|
91
98
|
```Bash
|
92
|
-
rake gutentag:install:migrations
|
93
|
-
|
99
|
+
bundle exec rake gutentag:install:migrations
|
100
|
+
bundle exec rails generate gutentag:migration_versions
|
101
|
+
bundle exec rake db:migrate
|
94
102
|
```
|
95
103
|
|
96
104
|
If you're using UUID primary keys, make sure you alter the migration files before running `db:migrate` to use UUIDs for the `taggable_id` foreign key column (as noted in [issue 57](https://github.com/pat/gutentag/issues/57).)
|
@@ -1,8 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
ActiveRecord::Migration : ActiveRecord::Migration[4.2]
|
5
|
-
class GutentagTables < superclass
|
3
|
+
class GutentagTables < ActiveRecord::Migration
|
6
4
|
def up
|
7
5
|
create_table :gutentag_taggings do |t|
|
8
6
|
t.integer :tag_id, :null => false
|
@@ -1,8 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
ActiveRecord::Migration : ActiveRecord::Migration[4.2]
|
5
|
-
class GutentagCacheCounter < superclass
|
3
|
+
class GutentagCacheCounter < ActiveRecord::Migration
|
6
4
|
def up
|
7
5
|
add_column :gutentag_tags, :taggings_count, :integer, :default => 0
|
8
6
|
add_index :gutentag_tags, :taggings_count
|
@@ -1,8 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
ActiveRecord::Migration : ActiveRecord::Migration[4.2]
|
5
|
-
class NoNullCounters < superclass
|
3
|
+
class NoNullCounters < ActiveRecord::Migration
|
6
4
|
def up
|
7
5
|
change_column :gutentag_tags, :taggings_count, :integer,
|
8
6
|
:default => 0,
|
data/gutentag.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "gutentag"
|
5
|
-
s.version = "2.
|
5
|
+
s.version = "2.6.0"
|
6
6
|
s.authors = ["Pat Allan"]
|
7
7
|
s.email = ["pat@freelancing-gods.com"]
|
8
8
|
s.homepage = "https://github.com/pat/gutentag"
|
@@ -16,7 +16,7 @@ Gem::Specification.new do |s|
|
|
16
16
|
|
17
17
|
s.add_runtime_dependency "activerecord", ">= 3.2.0"
|
18
18
|
|
19
|
-
s.add_development_dependency "appraisal", "~> 2.3"
|
19
|
+
# s.add_development_dependency "appraisal", "~> 2.3"
|
20
20
|
s.add_development_dependency "bundler", ">= 1.17"
|
21
21
|
s.add_development_dependency "combustion", "~> 1.1"
|
22
22
|
s.add_development_dependency "database_cleaner", "~> 1.6"
|
data/lib/gutentag/engine.rb
CHANGED
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails/generators"
|
4
|
+
|
5
|
+
module Gutentag
|
6
|
+
module Generators
|
7
|
+
class MigrationVersionsGenerator < Rails::Generators::Base
|
8
|
+
desc "Update the ActiveRecord version in Gutentag migrations"
|
9
|
+
|
10
|
+
def update_migration_versions
|
11
|
+
if ::ActiveRecord::VERSION::MAJOR < 5
|
12
|
+
puts "No changes required"
|
13
|
+
else
|
14
|
+
migration_files.each do |file|
|
15
|
+
gsub_file file,
|
16
|
+
/< ActiveRecord::Migration$/,
|
17
|
+
"< ActiveRecord::Migration[#{rails_version}]"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def migration_files
|
25
|
+
Dir[Rails.root.join("db/migrate/*.rb")].select do |path|
|
26
|
+
known_migration_names.any? do |known|
|
27
|
+
File.basename(path)[/\A\d+_#{known}\.gutentag.rb\z/]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def known_migration_names
|
33
|
+
@known_migration_names ||= begin
|
34
|
+
Dir[File.join(__dir__, "../../../db/migrate/*.rb")].collect do |path|
|
35
|
+
File.basename(path).gsub(/\A\d+_/, "").gsub(/\.rb\z/, "")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def rails_version
|
41
|
+
@rails_version ||= [
|
42
|
+
::ActiveRecord::VERSION::MAJOR,
|
43
|
+
::ActiveRecord::VERSION::MINOR
|
44
|
+
].join(".")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -8,7 +8,7 @@ class Gutentag::TaggedWith::Query
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def call
|
11
|
-
model.where "#{model_id}
|
11
|
+
model.where "#{model_id} #{operator} (#{query.to_sql})"
|
12
12
|
end
|
13
13
|
|
14
14
|
private
|
@@ -20,8 +20,16 @@ class Gutentag::TaggedWith::Query
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def query
|
23
|
-
return taggable_ids_query if
|
23
|
+
return taggable_ids_query if match_any_or_none? || values.length == 1
|
24
24
|
|
25
25
|
taggable_ids_query.having("COUNT(*) = #{values.length}").group(:taggable_id)
|
26
26
|
end
|
27
|
+
|
28
|
+
def operator
|
29
|
+
match == :none ? "NOT IN" : "IN"
|
30
|
+
end
|
31
|
+
|
32
|
+
def match_any_or_none?
|
33
|
+
%i[any none].include?(match)
|
34
|
+
end
|
27
35
|
end
|
@@ -160,6 +160,26 @@ RSpec.describe Gutentag::ActiveRecord do
|
|
160
160
|
it { is_expected.not_to include oregon_article }
|
161
161
|
end
|
162
162
|
|
163
|
+
context "matching excluding one tag" do
|
164
|
+
subject do
|
165
|
+
Article.tagged_with(:names => %w[ melbourne ], :match => :none)
|
166
|
+
end
|
167
|
+
|
168
|
+
it { expect(subject.count).to eq 1 }
|
169
|
+
it { is_expected.to include oregon_article }
|
170
|
+
it do
|
171
|
+
is_expected.not_to include melbourne_oregon_article, melbourne_article
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
context "matching excluding all tags" do
|
176
|
+
subject do
|
177
|
+
Article.tagged_with(:names => %w[ melbourne oregon ], :match => :none)
|
178
|
+
end
|
179
|
+
|
180
|
+
it { expect(subject.count).to eq 0 }
|
181
|
+
end
|
182
|
+
|
163
183
|
it "should work on STI subclasses" do
|
164
184
|
thinkpiece = Thinkpiece.create! :tag_names => ["pancakes"]
|
165
185
|
|
data/spec/spec_helper.rb
CHANGED
@@ -6,7 +6,8 @@ Bundler.require :default, :development
|
|
6
6
|
|
7
7
|
Dir["#{__dir__}/support/**/*.rb"].sort.each { |file| require file }
|
8
8
|
|
9
|
-
Combustion.initialize! :active_record
|
9
|
+
Combustion.initialize! :active_record, :database_migrate => false
|
10
|
+
AdjustMigrations.call(Combustion::Application)
|
10
11
|
ActiveSupport.run_load_hooks :gutentag unless defined?(Gutentag::Engine)
|
11
12
|
|
12
13
|
require "rspec/rails"
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "fileutils"
|
4
|
+
require "gutentag/generators/migration_versions_generator"
|
5
|
+
|
6
|
+
class AdjustMigrations
|
7
|
+
def self.call(application)
|
8
|
+
new(application).call
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(application)
|
12
|
+
@application = application
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
copy_migrations_to_app
|
17
|
+
run_generator
|
18
|
+
run_migrations
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
attr_reader :application
|
24
|
+
|
25
|
+
def copy_migrations_to_app
|
26
|
+
FileUtils.mkdir_p application.root.join("db/migrate")
|
27
|
+
|
28
|
+
Dir["#{__dir__}/../../db/migrate/*.rb"].each do |file|
|
29
|
+
name = File.basename(file.gsub(/rb\z/, "gutentag.rb"))
|
30
|
+
destination = application.root.join("db/migrate/#{name}")
|
31
|
+
|
32
|
+
FileUtils.cp file, destination.to_s
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def migration_context
|
37
|
+
if ActiveRecord::MigrationContext.instance_method(:initialize).arity <= 1
|
38
|
+
ActiveRecord::MigrationContext.new migration_paths
|
39
|
+
else
|
40
|
+
ActiveRecord::MigrationContext.new(
|
41
|
+
migration_paths, ActiveRecord::Base.connection.schema_migration
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def migration_paths
|
47
|
+
application.root.join("db/migrate")
|
48
|
+
end
|
49
|
+
|
50
|
+
def run_generator
|
51
|
+
Gutentag::Generators::MigrationVersionsGenerator.start(
|
52
|
+
["--quiet"], :destination_root => application.root
|
53
|
+
)
|
54
|
+
end
|
55
|
+
|
56
|
+
def run_migrations
|
57
|
+
if ActiveRecord::VERSION::STRING.to_f >= 5.2
|
58
|
+
migration_context.migrate
|
59
|
+
else
|
60
|
+
ActiveRecord::Migrator.migrate migration_paths, nil
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gutentag
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pat Allan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-07-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -24,20 +24,6 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 3.2.0
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: appraisal
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '2.3'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '2.3'
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: bundler
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -167,6 +153,7 @@ files:
|
|
167
153
|
- lib/gutentag/change_state.rb
|
168
154
|
- lib/gutentag/dirty.rb
|
169
155
|
- lib/gutentag/engine.rb
|
156
|
+
- lib/gutentag/generators/migration_versions_generator.rb
|
170
157
|
- lib/gutentag/persistence.rb
|
171
158
|
- lib/gutentag/remove_unused.rb
|
172
159
|
- lib/gutentag/tag_names.rb
|
@@ -191,6 +178,7 @@ files:
|
|
191
178
|
- spec/models/gutentag/tag_spec.rb
|
192
179
|
- spec/models/gutentag/tagging_spec.rb
|
193
180
|
- spec/spec_helper.rb
|
181
|
+
- spec/support/adjust_migrations.rb
|
194
182
|
- spec/support/mysql.rb
|
195
183
|
homepage: https://github.com/pat/gutentag
|
196
184
|
licenses:
|