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 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: