gutentag 2.4.1 → 2.5.4

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: 53b60a0cb99836a7c475d6fee7b431f99e38c16976f914e3591e86530c1d5b7b
4
- data.tar.gz: 564c325549cf3f51ceb24a5986a06d5ad66b81f1a07b948a1875b4e1d8ebead5
3
+ metadata.gz: 7af5fa8abd650550bd231819b8b4f043a17a15f0afba13dc443bf1b42ddd7a26
4
+ data.tar.gz: 7e22c0cc2a8c0de4840264b1e9cceb62c4504fc8df5d0e636a4894aa298152b5
5
5
  SHA512:
6
- metadata.gz: dcb6dba995fc07e770dbd605d667501dba90ed153c6c40ff825e53276890a2a7fb2e5d4f13cef3573a094d0b25fb1645baa956aeccdf3e1bfad8e6b0f8ade58e
7
- data.tar.gz: df7591b2ed083abb732c447ecf1b916d540edc168b4542bca99fe41e03e8135f2cee6745b2a43d2e68cc9466da411e578db4bac40264123d3cf88ee5da84b502
6
+ metadata.gz: 44ebaff249f6bba8798d98944177e3eac9569dc7731a3814add6e10fa1b2c5db1f491175e00bda53a25d84d6a96bdd622a5a812adac032017234c54864072002
7
+ data.tar.gz: fd440589741ffe77dfbde8649095c2bb5fae9a656d5b0cfb110390a8e156d49840cbead9a0e1e19d01a19a527a2d2e85dbd60e31a807fe25c6e2f746e5b59c55
@@ -0,0 +1,90 @@
1
+ name: CI
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ test:
7
+ runs-on: ubuntu-18.04
8
+
9
+ strategy:
10
+ fail-fast: false
11
+ matrix:
12
+ ruby: [ '2.4', '2.5', '2.6', '2.7', '3.0' ]
13
+ bundler: [ '1.17.3', '2.1.4' ]
14
+ database: [ 'mysql', 'postgresql', 'sqlite' ]
15
+ exclude:
16
+ - ruby: '2.4'
17
+ bundler: '2.1.4'
18
+ - ruby: '2.5'
19
+ bundler: '2.1.4'
20
+ - ruby: '2.6'
21
+ bundler: '2.1.4'
22
+ - ruby: '2.7'
23
+ bundler: '1.17.3'
24
+ - ruby: '3.0'
25
+ bundler: '1.17.3'
26
+
27
+ services:
28
+ postgres:
29
+ image: postgres:10
30
+ env:
31
+ POSTGRES_USER: root
32
+ POSTGRES_PASSWORD: gutentag
33
+ POSTGRES_DB: test
34
+ ports: ['5432:5432']
35
+ # needed because the postgres container does not provide a healthcheck
36
+ options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
37
+
38
+ mysql:
39
+ image: mysql:5.7
40
+ env:
41
+ MYSQL_ROOT_PASSWORD: gutentag
42
+ MYSQL_DATABASE: test
43
+ ports: ['3306:3306']
44
+ options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
45
+
46
+ steps:
47
+ - name: Check out code
48
+ uses: actions/checkout@v2
49
+ - name: Set up ruby
50
+ uses: ruby/setup-ruby@v1
51
+ with:
52
+ ruby-version: ${{ matrix.ruby }}
53
+ bundler: ${{ matrix.bundler }}
54
+ bundler-cache: true
55
+
56
+ - name: Set up Bundler
57
+ run: |
58
+ export BUNDLER_VERSION=${{ matrix.bundler }}
59
+ export BUNDLE_PATH=$PWD/vendor/bundle
60
+
61
+ gem update --system
62
+
63
+ bundle _${{ matrix.bundler }}_ config set path $PWD/$BUNDLE_PATH
64
+ bundle _${{ matrix.bundler }}_ install --jobs=4 --retry=3
65
+ bundle _${{ matrix.bundler }}_ update
66
+ - name: Set up Appraisal
67
+ run: bundle exec appraisal update
68
+ - name: Test
69
+ env:
70
+ CI: "true"
71
+ DATABASE: ${{ matrix.database }}
72
+ DB_USERNAME: root
73
+ DB_PASSWORD: gutentag
74
+ DB_HOST: 127.0.0.1
75
+ run: bundle exec appraisal rspec
76
+
77
+ rubocop:
78
+ runs-on: ubuntu-18.04
79
+
80
+ steps:
81
+ - name: Check out code
82
+ uses: actions/checkout@v2
83
+ - name: Set up ruby
84
+ uses: ruby/setup-ruby@v1
85
+ with:
86
+ ruby-version: 2.7
87
+ bundler: 2.1.4
88
+ bundler-cache: true
89
+ - name: Rubocop
90
+ run: bundle exec rubocop
data/.rubocop.yml CHANGED
@@ -1,13 +1,16 @@
1
1
  inherit_from:
2
2
  - https://gist.githubusercontent.com/pat/ba3b8ffb1901bfe5439b460943b6b019/raw/.rubocop.yml
3
3
 
4
+ require: rubocop-performance
5
+
4
6
  AllCops:
5
- TargetRubyVersion: 2.2
7
+ TargetRubyVersion: 2.3
6
8
  Exclude:
7
9
  - gemfiles/*.gemfile
10
+ - vendor/**/*
8
11
 
9
- Layout/AlignHash:
10
- EnforcedHashRocketStyle: table
12
+ Bundler/DuplicatedGem:
13
+ Enabled: false
11
14
 
12
15
  Metrics/MethodLength:
13
16
  Exclude:
@@ -22,5 +25,18 @@ Style/MultilineTernaryOperator:
22
25
  Exclude:
23
26
  - db/migrate/*.rb
24
27
 
25
- Style/SafeNavigation:
26
- Enabled: false
28
+ # 0.80
29
+
30
+ Style/HashEachMethods:
31
+ Enabled: true
32
+ Style/HashTransformKeys:
33
+ Enabled: true
34
+ Style/HashTransformValues:
35
+ Enabled: true
36
+
37
+ # 0.81
38
+
39
+ Lint/RaiseException:
40
+ Enabled: true
41
+ Lint/StructNewOverride:
42
+ Enabled: true
data/Appraisals CHANGED
@@ -1,10 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- appraise "rails_3_2" do
4
- gem "rails", "~> 3.2.22.5"
5
- gem "mysql2", "~> 0.3.10", :platform => :ruby
6
- end if RUBY_VERSION.to_f <= 2.2
7
-
8
3
  appraise "rails_4_0" do
9
4
  gem "rails", "~> 4.0.13"
10
5
  gem "mysql2", "~> 0.3.10", :platform => :ruby
@@ -22,26 +17,34 @@ appraise "rails_4_2" do
22
17
  gem "activerecord-jdbcmysql-adapter", "~> 1.3.23", :platform => :jruby
23
18
  gem "activerecord-jdbcpostgresql-adapter", "~> 1.3.23", :platform => :jruby
24
19
  gem "activerecord-jdbcsqlite3-adapter", "~> 1.3.23", :platform => :jruby
25
- end
20
+ end if RUBY_VERSION.to_f < 2.7
26
21
 
27
22
  appraise "rails_5_0" do
28
23
  gem "rails", "~> 5.0.3"
29
24
  gem "mysql2", "~> 0.4.0", :platform => :ruby
30
- end if RUBY_VERSION.to_f >= 2.2
25
+ end if RUBY_VERSION.to_f >= 2.2 && RUBY_VERSION.to_f <= 2.7
31
26
 
32
27
  appraise "rails_5_1" do
33
28
  gem "rails", "~> 5.1.1"
34
29
  gem "mysql2", "~> 0.4.0", :platform => :ruby
35
- end if RUBY_VERSION.to_f >= 2.2
30
+ end if RUBY_VERSION.to_f >= 2.2 && RUBY_VERSION.to_f <= 2.7
36
31
 
37
32
  appraise "rails_5_2" do
38
33
  gem "rails", "~> 5.2.0"
39
34
  gem "pg", "~> 1.0", :platform => :ruby
40
35
  gem "mysql2", "~> 0.5.0", :platform => :ruby
41
- end if RUBY_VERSION.to_f >= 2.2
36
+ end if RUBY_VERSION.to_f >= 2.2 && RUBY_VERSION.to_f <= 2.7
42
37
 
43
38
  appraise "rails_6_0" do
44
- gem "rails", "~> 6.0.0.beta1"
45
- gem "pg", "~> 1.0", :platform => :ruby
46
- gem "mysql2", "~> 0.5.0", :platform => :ruby
39
+ gem "rails", "~> 6.0.0"
40
+ gem "pg", "~> 1.0", :platform => :ruby
41
+ gem "mysql2", "~> 0.5.0", :platform => :ruby
42
+ gem "sqlite3", "~> 1.4", :platform => :ruby
43
+ end if RUBY_VERSION.to_f >= 2.5 && RUBY_PLATFORM != "java"
44
+
45
+ appraise "rails_6_1" do
46
+ gem "rails", "~> 6.1.0"
47
+ gem "pg", "~> 1.0", :platform => :ruby
48
+ gem "mysql2", "~> 0.5.0", :platform => :ruby
49
+ gem "sqlite3", "~> 1.4", :platform => :ruby
47
50
  end if RUBY_VERSION.to_f >= 2.5 && RUBY_PLATFORM != "java"
data/CHANGELOG.md CHANGED
@@ -2,6 +2,43 @@
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.5.4 - 2021-02-21
6
+
7
+ ### Fixed
8
+
9
+ * Don't apply the tag length validation when `ActiveRecord::ConnectionNotEstablished` exceptions are raised. ([John Duff](https://github.com/jduff) in [#77](https://github.com/pat/gutentag/pull/77)).
10
+
11
+ ## 2.5.3 - 2020-06-28
12
+
13
+ ### Fixed
14
+
15
+ * Use `saved_change_to_tag_names?` instead of `tag_names_previously_changed?` for Rails 5.1+ ([Morten Trolle](https://github.com/mtrolle) in [#70](https://github.com/pat/gutentag/pull/70)).
16
+ * `Gutentag::Tag.names_for_scope` now handles empty scopes ([Mike Gunderloy](https://github.com/ffmike) in [#73](https://github.com/pat/gutentag/pull/73)).
17
+
18
+ ## 2.5.2 - 2019-07-08
19
+
20
+ ### Fixed
21
+
22
+ * `tag_names` will no longer be referenced as a database column when tagged models are requested in joins in Rails 4.2 (as reported in [issue #67](https://github.com/pat/gutentag/issues/67)).
23
+
24
+ ## 2.5.1 - 2019-05-10
25
+
26
+ ### Fixed
27
+
28
+ * Ensuring consistent behaviour for tag_names array - names are not duplicated, and are normalised prior to saving (as discussed in [issue #66](https://github.com/pat/gutentag/issues/66)).
29
+
30
+ ## 2.5.0 - 2019-03-15
31
+
32
+ **Please note this release ends official support of Rails 3.2 and Ruby (MRI) 2.2.** The code currently still works on Ruby 2.2, and all features except for the new `Gutentag::Tag.names_for_scope` method work in Rails 3.2, but they're no longer tested against, and cannot be guaranteed to work in future releases.
33
+
34
+ ### Added
35
+
36
+ * Added the `Gutentag::Tag.names_for_scope(scope)` method, which accepts an ActiveRecord model or a relation, and returns all tag names associated to that model/relation.
37
+
38
+ ### Changed
39
+
40
+ * Removing support for MRI 2.2 and Rails 3.2.
41
+
5
42
  ## 2.4.1 - 2019-02-22
6
43
 
7
44
  ### Changed
data/Gemfile CHANGED
@@ -8,7 +8,12 @@ gem "test-unit", :platform => :ruby_22
8
8
 
9
9
  gem "mysql2", "~> 0.3", :platform => :ruby
10
10
  gem "pg", "~> 0.18", :platform => :ruby
11
- gem "sqlite3", "~> 1.3.13", :platform => :ruby
11
+
12
+ if RUBY_VERSION.to_f < 3.0
13
+ gem "sqlite3", "~> 1.3.13"
14
+ else
15
+ gem "sqlite3", "~> 1.4"
16
+ end
12
17
 
13
18
  gem "activerecord-jdbcmysql-adapter", ">= 1.3.23", :platform => :jruby
14
19
  gem "activerecord-jdbcpostgresql-adapter", ">= 1.3.23", :platform => :jruby
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Gutentag
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/gutentag.png)](http://badge.fury.io/rb/gutentag)
4
- [![Build Status](https://travis-ci.org/pat/gutentag.png?branch=master)](https://travis-ci.org/pat/gutentag)
5
- [![Code Climate](https://codeclimate.com/github/pat/gutentag.png)](https://codeclimate.com/github/pat/gutentag)
3
+ [![Gem Version](https://badge.fury.io/rb/gutentag.svg)](http://badge.fury.io/rb/gutentag)
4
+ [![Build Status](https://travis-ci.org/pat/gutentag.svg?branch=master)](https://travis-ci.org/pat/gutentag)
5
+ [![Code Climate](https://codeclimate.com/github/pat/gutentag.svg)](https://codeclimate.com/github/pat/gutentag)
6
6
 
7
7
  A good, simple, solid tagging extension for ActiveRecord.
8
8
 
@@ -16,6 +16,7 @@ If you want to know more, read [this blog post](http://freelancing-gods.com/post
16
16
  * [Installation](#installation)
17
17
  * [Upgrading](#upgrading)
18
18
  * [Configuration](#configuration)
19
+ * [Extending](#extending)
19
20
  * [Contribution](#contribution)
20
21
  * [Licence](#licence)
21
22
 
@@ -72,15 +73,17 @@ Article.tagged_with(:ids => [tag_a.id, tag_b.id], :match => :all)
72
73
 
73
74
  These are the versions the test suite runs against. It's possible it may work on older versions of Ruby, but it definitely won't work on older versions of Rails.
74
75
 
75
- * Ruby: MRI v2.2-v2.6, JRuby v9.2.5
76
- * Rails/ActiveRecord: v3.2-v6.0
76
+ * Ruby: MRI v2.3-v2.6, JRuby v9.2.5
77
+ * Rails/ActiveRecord: v4.0-v6.0
78
+
79
+ If you're using MRI v2.2 and/or ActiveRecord v3.2, the last version of Gutentag that fully supported those versions is v2.4.1.
77
80
 
78
81
  ### Installing
79
82
 
80
83
  Get it into your Gemfile - and don't forget the version constraint!
81
84
 
82
85
  ```Ruby
83
- gem 'gutentag', '~> 2.4'
86
+ gem 'gutentag', '~> 2.5'
84
87
  ```
85
88
 
86
89
  Next: your tags get persisted to your database, so let's import and run the migrations to get the tables set up:
@@ -149,6 +152,19 @@ Gutentag.normaliser = lambda { |value| value.to_s.upcase }
149
152
 
150
153
  Gutentag ignores case by default, but can be customised to be case-sensitive by supplying your own validations and normaliser, as outlined by [Robin Mehner](https://github.com/rmehner) in [issue 42](https://github.com/pat/gutentag/issues/42). Further changes may be required for your schema though, depending on your database.
151
154
 
155
+ <h2 id="extending">Extending</h2>
156
+
157
+ If you need to extend Gutentag's models, you will need to wrap the `include` inside a `to_prepare` hook to ensure it's loaded consistently in all Rails environments:
158
+
159
+ ```ruby
160
+ # config/initializers/gutentag.rb or equivalent
161
+ Rails.application.config.to_prepare do
162
+ Gutentag::Tag.include TagExtensions
163
+ end
164
+ ```
165
+
166
+ Further discussion and examples of this can be found in [issue 65](https://github.com/pat/gutentag/issues/65).
167
+
152
168
  <h2 id="contribution">Contribution</h2>
153
169
 
154
170
  Please note that this project now has a [Contributor Code of Conduct](http://contributor-covenant.org/version/1/0/0/). By participating in this project you agree to abide by its terms.
@@ -19,6 +19,19 @@ class Gutentag::Tag < ActiveRecord::Base
19
19
  find_by_name(name) || create(:name => name)
20
20
  end
21
21
 
22
+ def self.names_for_scope(scope)
23
+ join_conditions = {:taggable_type => scope.name}
24
+ if scope.is_a?(ActiveRecord::Relation)
25
+ return Gutentag::Tag.none unless scope.current_scope.present?
26
+
27
+ join_conditions[:taggable_id] = scope.select(:id)
28
+ end
29
+
30
+ joins(:taggings).where(
31
+ Gutentag::Tagging.table_name => join_conditions
32
+ ).distinct.pluck(:name)
33
+ end
34
+
22
35
  def name=(value)
23
36
  super(Gutentag.normaliser.call(value))
24
37
  end
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.4.1"
5
+ s.version = "2.5.4"
6
6
  s.authors = ["Pat Allan"]
7
7
  s.email = ["pat@freelancing-gods.com"]
8
8
  s.homepage = "https://github.com/pat/gutentag"
@@ -16,11 +16,12 @@ 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.1.0"
20
- s.add_development_dependency "bundler", "~> 1.17"
21
- s.add_development_dependency "combustion", "~> 1.1"
22
- s.add_development_dependency "database_cleaner", "~> 1.6"
19
+ s.add_development_dependency "appraisal", "~> 2.3"
20
+ s.add_development_dependency "bundler", ">= 1.17"
21
+ s.add_development_dependency "combustion", "~> 1.1"
22
+ s.add_development_dependency "database_cleaner", "~> 1.6"
23
23
  s.add_development_dependency "rails"
24
- s.add_development_dependency "rspec-rails", "~> 3.1"
25
- s.add_development_dependency "rubocop", "~> 0.64.0"
24
+ s.add_development_dependency "rspec-rails", "~> 3.1"
25
+ s.add_development_dependency "rubocop", "~> 0.81.0"
26
+ s.add_development_dependency "rubocop-performance", "~> 1"
26
27
  end
@@ -31,7 +31,7 @@ class Gutentag::ActiveRecord
31
31
  end
32
32
 
33
33
  def add_attribute
34
- if legacy?
34
+ if ActiveRecord::VERSION::STRING.to_f <= 4.2
35
35
  model.define_attribute_method "tag_names"
36
36
  else
37
37
  model.attribute "tag_names", ActiveRecord::Type::Value.new,
@@ -2,6 +2,8 @@
2
2
 
3
3
  # For Rails 5.0+
4
4
  module Gutentag::ActiveRecord::InstanceMethods
5
+ AR_VERSION = ActiveRecord::VERSION::STRING.to_f
6
+
5
7
  # If the tag_names attribute was one of the modified values, then let's just
6
8
  # use the modifications, rather than overwriting the stored value.
7
9
  #
@@ -9,7 +11,12 @@ module Gutentag::ActiveRecord::InstanceMethods
9
11
  # the instance directly (e.g. article.tags << tag), which invokes the save
10
12
  # callbacks, but the old tag_names value is stored but not updated.
11
13
  def reset_tag_names
12
- return if tag_names_previously_changed?
14
+ # Rails 5.1 introduces major changes to how ActiveModel::Dirty works:
15
+ # https://github.com/pat/gutentag/pull/70#issuecomment-524605448
16
+ # For Rails <5.1 we'll use *_previously_changed?
17
+ # and for 5.1+ we'll use saved_change_to_*?
18
+ return if AR_VERSION < 5.1 && tag_names_previously_changed?
19
+ return if AR_VERSION >= 5.1 && saved_change_to_tag_names?
13
20
 
14
21
  # Update the underlying value rather than going through the setter, to
15
22
  # ensure this update doesn't get marked as a 'change'.
@@ -16,7 +16,7 @@ module Gutentag::ActiveRecord::InstanceMethods
16
16
  def tag_names=(names)
17
17
  names = Gutentag::TagNames.call(names)
18
18
 
19
- Gutentag.dirtier.call self, names if Gutentag.dirtier
19
+ Gutentag.dirtier.call self, names if Gutentag.dirtier.present?
20
20
 
21
21
  @tag_names = names
22
22
  end
@@ -8,22 +8,25 @@ module Gutentag::ActiveRecord::InstanceMethods
8
8
  def reset_tag_names
9
9
  # Update the underlying value rather than going through the setter, to
10
10
  # ensure this update doesn't get marked as a 'change'.
11
- self.tag_names = nil
11
+ @tag_names = nil
12
12
  end
13
13
 
14
14
  def tag_names
15
- # If the underlying value is nil, we've not requested this from the
16
- # database yet.
17
- if read_attribute("tag_names") { nil }.nil?
18
- self.tag_names = tags.pluck(:name)
15
+ @tag_names ||= begin
16
+ raw = tags.pluck(:name)
17
+ raw_write_attribute "tag_names", raw
18
+ raw
19
19
  end
20
-
21
- # Use ActiveRecord's underlying implementation with change tracking.
22
- super
23
20
  end
24
21
 
25
22
  def tag_names=(names)
26
- super Gutentag::TagNames.call(names)
23
+ new_names = Gutentag::TagNames.call names
24
+ return if new_names.sort == tag_names.sort
25
+
26
+ tag_names_will_change!
27
+
28
+ write_attribute "tag_names", new_names
29
+ @tag_names = new_names
27
30
  end
28
31
 
29
32
  private
@@ -4,6 +4,8 @@ class Gutentag::TagNames
4
4
  def self.call(names)
5
5
  return nil if names.nil?
6
6
 
7
- names.reject(&:blank?)
7
+ names.reject(&:blank?).uniq.collect do |name|
8
+ Gutentag.normaliser.call(name)
9
+ end
8
10
  end
9
11
  end
@@ -13,6 +13,7 @@ class Gutentag::TagValidations
13
13
  if ActiveRecord::VERSION::STRING.to_f > 4.0
14
14
  classes << ActiveRecord::NoDatabaseError
15
15
  end
16
+ classes << ActiveRecord::ConnectionNotEstablished
16
17
  classes << Mysql2::Error if defined?(::Mysql2)
17
18
  classes << PG::ConnectionBad if defined?(::PG)
18
19
  classes
@@ -36,7 +37,7 @@ class Gutentag::TagValidations
36
37
 
37
38
  def add_length_validation?
38
39
  klass.table_exists? && limit.present?
39
- rescue *DATABASE_ERROR_CLASSES
40
+ rescue *DATABASE_ERROR_CLASSES => _error
40
41
  warn <<-MESSAGE
41
42
  The database is not currently available, and so Gutentag was not able to set
42
43
  up tag validations completely (in particular: adding a length limit to match
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "spec_helper"
4
4
 
5
- describe "Removing unused" do
5
+ RSpec.describe "Removing unused" do
6
6
  let(:article) { Article.create }
7
7
 
8
8
  it "deletes only unused tags" do
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ RSpec.describe "Tag names for scopes" do
6
+ it "returns tag names for a given model" do
7
+ Article.create :tag_names => %w[ koala wombat ]
8
+ Article.create :tag_names => %w[ cassowary ]
9
+
10
+ expect(Gutentag::Tag.names_for_scope(Article)).
11
+ to match_array(%w[ koala wombat cassowary ])
12
+ end
13
+
14
+ it "returns tag names for a given scope" do
15
+ Article.create :title => "mammals", :tag_names => %w[ koala wombat ]
16
+ Article.create :title => "birds", :tag_names => %w[ cassowary ]
17
+
18
+ expect(Gutentag::Tag.names_for_scope(Article.where(:title => "mammals"))).
19
+ to match_array(%w[ koala wombat ])
20
+ end
21
+
22
+ it "does not duplicate tag names for a given model/scope" do
23
+ Article.create :tag_names => %w[ koala wombat ]
24
+ Article.create :tag_names => %w[ cassowary ]
25
+ Article.create :tag_names => %w[ cassowary wombat ]
26
+
27
+ expect(Gutentag::Tag.names_for_scope(Article)).
28
+ to match_array(%w[ koala wombat cassowary ])
29
+ end
30
+
31
+ it "returns an empty array for an empty scope" do
32
+ Article.create :title => "mammals", :tag_names => %w[ koala wombat ]
33
+ Article.create :title => "birds", :tag_names => %w[ cassowary ]
34
+
35
+ expect(Gutentag::Tag.names_for_scope(Article.where(:title => "reptiles"))).
36
+ to match_array([])
37
+ end
38
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "spec_helper"
4
4
 
5
- describe "Managing tags via names" do
5
+ RSpec.describe "Managing tags via names" do
6
6
  let(:article) { Article.create }
7
7
 
8
8
  it "returns tag names" do
@@ -70,6 +70,13 @@ describe "Managing tags via names" do
70
70
  expect(article.tags.collect(&:name)).to eq(%w[ portland oregon ruby ])
71
71
  end
72
72
 
73
+ it "does not repeat appended names that exist in the array of strings" do
74
+ article.tag_names = %w[ portland oregon ]
75
+ article.tag_names += %w[ oregon ruby ]
76
+
77
+ expect(article.tag_names).to match(%w[ portland oregon ruby ])
78
+ end
79
+
73
80
  it "removes a single tag name" do
74
81
  article.tag_names = %w[ portland oregon ]
75
82
  article.tag_names.delete "oregon"
@@ -99,6 +106,11 @@ describe "Managing tags via names" do
99
106
  expect(article.tags.collect(&:name)).to eq(%w[ portland ])
100
107
  end
101
108
 
109
+ it "normalises tag names" do
110
+ article.tag_names = %w[ Perth ]
111
+ expect(article.tag_names).to eq(%w[ perth ])
112
+ end
113
+
102
114
  it "allows setting of tag names on unpersisted objects" do
103
115
  article = Article.new :tag_names => %w[ melbourne pancakes ]
104
116
  article.save!
@@ -123,4 +135,8 @@ describe "Managing tags via names" do
123
135
 
124
136
  expect(article.tag_names).to eq(%w[ melbourne ])
125
137
  end
138
+
139
+ it "allows eager-loading of the model via an association" do
140
+ expect { Comment.eager_load(:article).to_a }.to_not raise_error
141
+ end
126
142
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "spec_helper"
4
4
 
5
- describe "Adding and removing tags" do
5
+ RSpec.describe "Adding and removing tags" do
6
6
  let(:article) { Article.create }
7
7
  let(:pancakes) { Gutentag::Tag.create :name => "pancakes" }
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "spec_helper"
4
4
 
5
- describe Gutentag::ActiveRecord do
5
+ RSpec.describe Gutentag::ActiveRecord do
6
6
  describe ".tagged_with" do
7
7
  let!(:melbourne_article) do
8
8
  article = Article.create :title => "Overview"
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "spec_helper"
4
4
 
5
- describe Gutentag do
5
+ RSpec.describe Gutentag do
6
6
  describe ".normalizer" do
7
7
  it "downcases the provided name" do
8
8
  expect(Gutentag.normaliser.call("Tasty Pancakes")).to eq("tasty pancakes")
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Comment < ActiveRecord::Base
4
+ belongs_to :article
5
+ end
@@ -2,11 +2,26 @@
2
2
  test:
3
3
  adapter: mysql2
4
4
  database: gutentag
5
- username: root
5
+ username: <%= ENV.fetch("DB_USERNAME", "root") %>
6
+ <% if ENV["DB_HOST"] %>
7
+ host: <%= ENV["DB_HOST"] %>
8
+ <% end %>
9
+ <% if ENV["DB_PASSWORD"] %>
10
+ password: <%= ENV["DB_PASSWORD"] %>
11
+ <% end %>
6
12
  <% elsif ENV["DATABASE"] == "postgres" %>
7
13
  test:
8
14
  adapter: postgresql
9
15
  database: gutentag
16
+ <% if ENV["DB_HOST"] %>
17
+ host: <%= ENV["DB_HOST"] %>
18
+ <% end %>
19
+ <% if ENV["DB_USERNAME"] %>
20
+ username: <%= ENV["DB_USERNAME"] %>
21
+ <% end %>
22
+ <% if ENV["DB_PASSWORD"] %>
23
+ password: <%= ENV["DB_PASSWORD"] %>
24
+ <% end %>
10
25
  <% else %>
11
26
  test:
12
27
  adapter: sqlite3
@@ -6,4 +6,10 @@ ActiveRecord::Schema.define do
6
6
  t.string :type
7
7
  t.timestamps :null => false
8
8
  end
9
+
10
+ create_table :comments, :force => true do |t|
11
+ t.references :article
12
+ t.string :name
13
+ t.text :text
14
+ end
9
15
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "spec_helper"
4
4
 
5
- describe Gutentag::Tag, :type => :model do
5
+ RSpec.describe Gutentag::Tag, :type => :model do
6
6
  describe ".find_by_name" do
7
7
  it "returns a tag with the same name" do
8
8
  existing = Gutentag::Tag.create! :name => "pancakes"
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "spec_helper"
4
4
 
5
- describe Gutentag::Tagging, :type => :model do
5
+ RSpec.describe Gutentag::Tagging, :type => :model do
6
6
  describe "#valid?" do
7
7
  let(:tag) { Gutentag::Tag.create! :name => "pancakes" }
8
8
  let(:taggable) { Article.create! }
data/spec/spec_helper.rb CHANGED
@@ -4,7 +4,7 @@ require "bundler/setup"
4
4
 
5
5
  Bundler.require :default, :development
6
6
 
7
- Dir["#{__dir__}/support/**/*.rb"].each { |file| require file }
7
+ Dir["#{__dir__}/support/**/*.rb"].sort.each { |file| require file }
8
8
 
9
9
  Combustion.initialize! :active_record
10
10
  ActiveSupport.run_load_hooks :gutentag unless defined?(Gutentag::Engine)
@@ -12,6 +12,8 @@ ActiveSupport.run_load_hooks :gutentag unless defined?(Gutentag::Engine)
12
12
  require "rspec/rails"
13
13
 
14
14
  RSpec.configure do |config|
15
+ config.disable_monkey_patching!
16
+
15
17
  if config.respond_to?(:use_transactional_tests)
16
18
  config.use_transactional_tests = false
17
19
  else
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.1
4
+ version: 2.5.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pat Allan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-22 00:00:00.000000000 Z
11
+ date: 2021-02-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -30,26 +30,26 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 2.1.0
33
+ version: '2.3'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 2.1.0
40
+ version: '2.3'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '1.17'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.17'
55
55
  - !ruby/object:Gem::Dependency
@@ -114,14 +114,28 @@ dependencies:
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: 0.64.0
117
+ version: 0.81.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 0.81.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop-performance
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '1'
118
132
  type: :development
119
133
  prerelease: false
120
134
  version_requirements: !ruby/object:Gem::Requirement
121
135
  requirements:
122
136
  - - "~>"
123
137
  - !ruby/object:Gem::Version
124
- version: 0.64.0
138
+ version: '1'
125
139
  description: A good, simple, solid tagging extension for ActiveRecord
126
140
  email:
127
141
  - pat@freelancing-gods.com
@@ -129,9 +143,9 @@ executables: []
129
143
  extensions: []
130
144
  extra_rdoc_files: []
131
145
  files:
146
+ - ".github/workflows/ci.yml"
132
147
  - ".gitignore"
133
148
  - ".rubocop.yml"
134
- - ".travis.yml"
135
149
  - Appraisals
136
150
  - CHANGELOG.md
137
151
  - Gemfile
@@ -163,11 +177,13 @@ files:
163
177
  - lib/gutentag/tagged_with/query.rb
164
178
  - spec/acceptance/dirty_state_spec.rb
165
179
  - spec/acceptance/removing_unused_spec.rb
180
+ - spec/acceptance/tag_names_for_scope_spec.rb
166
181
  - spec/acceptance/tag_names_spec.rb
167
182
  - spec/acceptance/tags_spec.rb
168
183
  - spec/gutentag/active_record_spec.rb
169
184
  - spec/gutentag_spec.rb
170
185
  - spec/internal/app/models/article.rb
186
+ - spec/internal/app/models/comment.rb
171
187
  - spec/internal/app/models/thinkpiece.rb
172
188
  - spec/internal/config/database.yml
173
189
  - spec/internal/db/schema.rb
@@ -195,8 +211,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
195
211
  - !ruby/object:Gem::Version
196
212
  version: '0'
197
213
  requirements: []
198
- rubyforge_project:
199
- rubygems_version: 2.7.6
214
+ rubygems_version: 3.1.2
200
215
  signing_key:
201
216
  specification_version: 4
202
217
  summary: Good Tags
data/.travis.yml DELETED
@@ -1,23 +0,0 @@
1
- language: ruby
2
- dist: xenial
3
- script: bundle exec appraisal rake
4
- rvm:
5
- - 2.2.10
6
- - 2.3.8
7
- - 2.4.5
8
- - 2.5.3
9
- - 2.6.1
10
- - jruby-9.2.5.0
11
- before_install:
12
- - gem install bundler --version 1.17.3
13
- install:
14
- - bundle _1.17.3_ install --jobs=3 --retry=3
15
- before_script:
16
- - bundle exec appraisal install
17
- env:
18
- - DATABASE=postgres
19
- - DATABASE=mysql
20
- - DATABASE=sqlite
21
- services:
22
- - mysql
23
- - postgresql