Add Ruby 3.1 to CI (#558)

* Add Ruby 3.1 to CI

Update Rubocop for recent Rubies
Disable Rubocop run for Rubies before Ruby 2.4
Quote '3.0' in the CI configuration to ensure it loads a 3.0.x Ruby
Set RUBYOPT="--disable_error_highlight" so Ruby 3.1 error matchers pass

* Add CHANGELOG.md entry

* Re-add deleted line from CHANGELOG.md

* Set minimum supported Ruby version to 2.4.

Remove a number of code bits designed to support Rubies below version 2.4

* Bump version.  Remove unneeded require from Gemfile.  Add require to spec/support file
This commit is contained in:
Peter Goldstein 2022-01-27 18:59:24 -08:00 committed by GitHub
parent 4dc015eb52
commit 3e57eb531f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 89 additions and 105 deletions

View File

@ -52,14 +52,12 @@ jobs:
fail-fast: false
matrix:
ruby:
- 3.0
- 2.7
- 2.6
- 2.5
- 2.4
- 2.3
- 2.2
- 2.1
- '3.1'
- '3.0'
- '2.7'
- '2.6'
- '2.5'
- '2.4'
steps:
- uses: actions/checkout@v2
- name: Set up Ruby
@ -70,6 +68,8 @@ jobs:
- name: Install dependencies
run: bundle install --jobs 4 --retry 3
- name: Run tests
env:
RUBYOPT: "--disable-error_highlight"
run: bundle exec rake
test-jruby:

View File

@ -9,7 +9,7 @@ AllCops:
inherit_from: .rubocop_todo.yml
# Disabled until we can use the squiggly heredoc (after deprecating Ruby <2.3)
Layout/IndentHeredoc:
Layout/HeredocIndentation:
Enabled: false
Metrics/ClassLength:
@ -43,3 +43,6 @@ Naming/FileName:
# boolean casting that we do.
Style/DoubleNegation:
Enabled: false
Style/HashSyntax:
Enabled: false

View File

@ -17,6 +17,7 @@ Any violations of this scheme are considered to be bugs.
### Changed
* Your contribution here.
* [#558](https://github.com/hashie/hashie/pull/558): Test with Ruby 3.1 - [@petergoldstein](https://github.com/petergoldstein).
### Deprecated

14
Gemfile
View File

@ -9,20 +9,12 @@ group :development do
gem 'guard-rspec', '~> 4.3.1', require: false
gem 'guard-yield', '~> 0.1.0', require: false
gem 'pry'
gem 'pry-stack_explorer', platforms: %i[ruby_19 ruby_20 ruby_21]
gem 'rubocop', '0.52.1'
gem 'rubocop', '~> 1.0'
group :test do
# ActiveSupport required to test compatibility with ActiveSupport Core Extensions.
# rubocop:disable Bundler/DuplicatedGem
require File.expand_path('../lib/hashie/extensions/ruby_version', __FILE__)
if Hashie::Extensions::RubyVersion.new(RUBY_VERSION) >=
Hashie::Extensions::RubyVersion.new('2.4.0')
gem 'activesupport', '~> 5.x', require: false
else
gem 'activesupport', '~> 4.x', require: false
end
# rubocop:enable Bundler/DuplicatedGem
gem 'activesupport', '~> 5.x', require: false
gem 'rake'
gem 'rspec', '~> 3'
gem 'rspec-pending_for', '~> 0.1'

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
require_relative 'spec/support/integration_specs'
run_all = lambda do |*|

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
require 'rubygems'
require 'bundler'
Bundler.setup
@ -16,6 +18,7 @@ RuboCop::RakeTask.new(:rubocop)
require_relative 'spec/support/integration_specs'
task :integration_specs do
next if ENV['CI']
status_codes = []
handler = lambda do |status_code|
status_codes << status_code unless status_code.zero?

View File

@ -1,4 +1,5 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'bundler/setup'
require 'hashie'

View File

@ -24,5 +24,7 @@ Gem::Specification.new do |gem|
}
end
gem.required_ruby_version = '>= 2.4'
gem.add_development_dependency 'bundler'
end

View File

@ -17,14 +17,7 @@ module Hashie
}.freeze
ABSTRACT_CORE_TYPES =
if RubyVersion.new(RUBY_VERSION) >= RubyVersion.new('2.4.0')
{ Numeric => [Integer, Float, Complex, Rational] }
else
{
Integer => [Fixnum, Bignum],
Numeric => [Fixnum, Bignum, Float, Complex, Rational]
}
end
{ Numeric => [Integer, Float, Complex, Rational] }
def self.included(base)
base.send :include, InstanceMethods

View File

@ -322,22 +322,18 @@ module Hashie
self.class.new(other_hash).merge(self)
end
with_minimum_ruby('2.3.0') do
def dig(*keys)
super(*keys.map { |key| convert_key(key) })
end
def dig(*keys)
super(*keys.map { |key| convert_key(key) })
end
with_minimum_ruby('2.4.0') do
def transform_values(&blk)
self.class.new(super(&blk))
end
def transform_values(&blk)
self.class.new(super(&blk))
end
# Returns a new instance of the class it was called on, with nil values
# removed.
def compact
self.class.new(super)
end
# Returns a new instance of the class it was called on, with nil values
# removed.
def compact
self.class.new(super)
end
with_minimum_ruby('2.5.0') do

View File

@ -1,3 +1,3 @@
module Hashie
VERSION = '5.0.1'.freeze
VERSION = '5.1.0'.freeze
end

View File

@ -1,28 +1,26 @@
require 'spec_helper'
describe Array do
with_minimum_ruby('2.3.0') do
describe '#dig' do
let(:array) { Hashie::Array.new(%i[a b c]) }
describe '#dig' do
let(:array) { Hashie::Array.new(%i[a b c]) }
it 'works with a string index' do
expect(array.dig('0')).to eq(:a)
it 'works with a string index' do
expect(array.dig('0')).to eq(:a)
end
it 'works with a numeric index' do
expect(array.dig(1)).to eq(:b)
end
context 'when array is empty' do
let(:array) { Hashie::Array.new([]) }
it 'works with a first numeric and next string index' do
expect(array.dig(0, 'hello')).to eq(nil)
end
it 'works with a numeric index' do
expect(array.dig(1)).to eq(:b)
end
context 'when array is empty' do
let(:array) { Hashie::Array.new([]) }
it 'works with a first numeric and next string index' do
expect(array.dig(0, 'hello')).to eq(nil)
end
it 'throws an error with first string and next numeric index' do
expect { array.dig('hello', 0) }.to raise_error(TypeError)
end
it 'throws an error with first string and next numeric index' do
expect { array.dig('hello', 0) }.to raise_error(TypeError)
end
end
end

View File

@ -563,13 +563,7 @@ describe Hashie::Extensions::Coercion do
end
it 'raises a CoercionError when coercion is not possible' do
type =
if Hashie::Extensions::RubyVersion.new(RUBY_VERSION) >=
Hashie::Extensions::RubyVersion.new('2.4.0')
Integer
else
Fixnum
end
type = Integer
subject.coerce_value type, Symbol
expect { instance[:hi] = 1 }.to raise_error(
@ -578,13 +572,7 @@ describe Hashie::Extensions::Coercion do
end
it 'coerces Integer to String' do
type =
if Hashie::Extensions::RubyVersion.new(RUBY_VERSION) >=
Hashie::Extensions::RubyVersion.new('2.4.0')
Integer
else
Fixnum
end
type = Integer
subject.coerce_value type, String

View File

@ -649,8 +649,7 @@ describe Hashie::Mash do
context 'when key does not exist' do
it 'raises KeyError' do
error = RUBY_VERSION =~ /1.8/ ? IndexError : KeyError
expect { mash.fetch(:two) }.to raise_error(error)
expect { mash.fetch(:two) }.to raise_error(KeyError)
end
context 'with default value given' do
@ -980,44 +979,40 @@ describe Hashie::Mash do
end
end
with_minimum_ruby('2.3.0') do
describe '#dig' do
subject { described_class.new(a: { b: 1 }) }
describe '#dig' do
subject { described_class.new(a: { b: 1 }) }
it 'accepts both string and symbol as key' do
expect(subject.dig(:a, :b)).to eq(1)
expect(subject.dig('a', 'b')).to eq(1)
end
it 'accepts both string and symbol as key' do
expect(subject.dig(:a, :b)).to eq(1)
expect(subject.dig('a', 'b')).to eq(1)
end
context 'when the Mash wraps a Hashie::Array' do
it 'handles digging into an array' do
mash = described_class.new(alphabet: { first_three: Hashie::Array['a', 'b', 'c'] })
context 'when the Mash wraps a Hashie::Array' do
it 'handles digging into an array' do
mash = described_class.new(alphabet: { first_three: Hashie::Array['a', 'b', 'c'] })
expect(mash.dig(:alphabet, :first_three, 0)).to eq 'a'
end
expect(mash.dig(:alphabet, :first_three, 0)).to eq 'a'
end
end
end
with_minimum_ruby('2.4.0') do
describe '#transform_values' do
subject(:mash) { described_class.new(a: 1) }
describe '#transform_values' do
subject(:mash) { described_class.new(a: 1) }
it 'returns a Hashie::Mash' do
expect(mash.transform_values(&:to_s)).to be_kind_of(described_class)
end
it 'returns a Hashie::Mash' do
expect(mash.transform_values(&:to_s)).to be_kind_of(described_class)
end
it 'transforms the value' do
expect(mash.transform_values(&:to_s).a).to eql('1')
end
it 'transforms the value' do
expect(mash.transform_values(&:to_s).a).to eql('1')
end
context 'when using with subclass' do
let(:subclass) { Class.new(Hashie::Mash) }
subject(:sub_mash) { subclass.new(a: 1).transform_values { |a| a + 2 } }
context 'when using with subclass' do
let(:subclass) { Class.new(Hashie::Mash) }
subject(:sub_mash) { subclass.new(a: 1).transform_values { |a| a + 2 } }
it 'creates an instance of subclass' do
expect(sub_mash).to be_kind_of(subclass)
end
it 'creates an instance of subclass' do
expect(sub_mash).to be_kind_of(subclass)
end
end

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
namespace :perf do
task :setup do
require 'omniauth'
@ -12,6 +14,7 @@ namespace :perf do
def call_app(path = ENV['GET_PATH'] || '/')
result = @app.get(path)
raise "Did not succeed #{result.body}" unless result.status == 200
result
end
end

View File

@ -1,10 +1,17 @@
require File.expand_path('../../../lib/hashie/extensions/ruby_version', __FILE__)
# Generates the bundle command for running an integration test
#
# @param [String] integration the integration folder to run
# @param [String] command the command to run
# @return [String]
def integration_command(integration, command)
"#{integration_gemfile(integration)} #{command}"
if Hashie::Extensions::RubyVersion.new(RUBY_VERSION) >=
Hashie::Extensions::RubyVersion.new('3.1.0')
ruby_opts = "RUBYOPT=--disable-error_highlight "
end
"#{ruby_opts}#{integration_gemfile(integration)} #{command}"
end
# Generates the Gemfile for an integration