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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7af5fa8abd650550bd231819b8b4f043a17a15f0afba13dc443bf1b42ddd7a26
4
- data.tar.gz: 7e22c0cc2a8c0de4840264b1e9cceb62c4504fc8df5d0e636a4894aa298152b5
3
+ metadata.gz: b49f3b3dd099ef714f2b23fa1d0e1b08059c59c15447cdece6ee07ac1a0a1272
4
+ data.tar.gz: c0ef3dd657f3c0b6fe216b80807f74bed2abbdefcbd2c6c467176a8ca16b38a2
5
5
  SHA512:
6
- metadata.gz: 44ebaff249f6bba8798d98944177e3eac9569dc7731a3814add6e10fa1b2c5db1f491175e00bda53a25d84d6a96bdd622a5a812adac032017234c54864072002
7
- data.tar.gz: fd440589741ffe77dfbde8649095c2bb5fae9a656d5b0cfb110390a8e156d49840cbead9a0e1e19d01a19a527a2d2e85dbd60e31a807fe25c6e2f746e5b59c55
6
+ metadata.gz: ffeef43eb46712c0a261fc569db0571cc2ad66b68254cac89afbba58df15b8f41142b9401f170997608d692d81c353b744b1d71756520f7a80e4cb9c84caeb37
7
+ data.tar.gz: 80996c6d6b7f8addfb86092b80c8ffed4c28f60629db98e126fab4303865b215c4efbf76de30e9d5c8ab74e7a76859fbdfb9fff5d1c16905153f9a91d1aa6e7c
data/.gitignore CHANGED
@@ -2,4 +2,5 @@
2
2
  gemfiles
3
3
  pkg/*
4
4
  spec/internal/db/*.sqlite
5
+ spec/internal/db/migrate/
5
6
  .rubocop-*-yml
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
@@ -4,6 +4,10 @@ source "https://rubygems.org"
4
4
 
5
5
  gemspec
6
6
 
7
+ gem "appraisal",
8
+ :git => "https://github.com/marcotc/appraisal.git",
9
+ :branch => "explicit-require-set"
10
+
7
11
  gem "test-unit", :platform => :ruby_22
8
12
 
9
13
  gem "mysql2", "~> 0.3", :platform => :ruby
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 and run the migrations to get the tables set up:
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
- rake db:migrate
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
- superclass = ActiveRecord::VERSION::MAJOR < 5 ?
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
- superclass = ActiveRecord::VERSION::MAJOR < 5 ?
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
- superclass = ActiveRecord::VERSION::MAJOR < 5 ?
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.4"
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"
@@ -2,4 +2,8 @@
2
2
 
3
3
  class Gutentag::Engine < Rails::Engine
4
4
  engine_name :gutentag
5
+
6
+ generators do
7
+ require "gutentag/generators/migration_versions_generator"
8
+ end
5
9
  end
@@ -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} IN (#{query.to_sql})"
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 match == :any || values.length == 1
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.5.4
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-02-21 00:00:00.000000000 Z
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: