gutentag 2.5.4 → 2.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|