diff options
-rw-r--r-- | .rubocop_todo.yml | 6 | ||||
-rw-r--r-- | lib/hashie/mash.rb | 42 | ||||
-rw-r--r-- | spec/hashie/mash_spec.rb | 151 |
3 files changed, 196 insertions, 3 deletions
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index ab2db99..bc15a46 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2019-07-17 09:23:49 -0400 using RuboCop version 0.52.1. +# on 2019-08-13 23:33:30 -0400 using RuboCop version 0.52.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -13,13 +13,13 @@ Metrics/AbcSize: # Offense count: 2 # Configuration parameters: CountComments. Metrics/ClassLength: - Max: 221 + Max: 266 # Offense count: 7 Metrics/CyclomaticComplexity: Max: 11 -# Offense count: 19 +# Offense count: 18 # Configuration parameters: CountComments. Metrics/MethodLength: Max: 28 diff --git a/lib/hashie/mash.rb b/lib/hashie/mash.rb index 06cef59..bac93a4 100644 --- a/lib/hashie/mash.rb +++ b/lib/hashie/mash.rb @@ -207,6 +207,31 @@ module Hashie super(*keys.map { |key| convert_key(key) }) 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, using its keys as + # values, and its values as keys. The new values and keys will always be + # strings. + def invert + self.class.new(super) + end + + # Returns a new instance of the class it was called on, containing elements + # for which the given block returns false. + def reject(&blk) + self.class.new(super(&blk)) + end + + # Returns a new instance of the class it was called on, containing elements + # for which the given block returns true. + def select(&blk) + self.class.new(super(&blk)) + end + alias regular_dup dup # Duplicates the current mash as a new mash. def dup @@ -320,6 +345,23 @@ module Hashie end end + with_minimum_ruby('2.4.0') do + def transform_values(&blk) + self.class.new(super(&blk)) + end + end + + with_minimum_ruby('2.5.0') do + def slice(*keys) + string_keys = keys.map { |key| convert_key(key) } + self.class.new(super(*string_keys)) + end + + def transform_keys(&blk) + self.class.new(super(&blk)) + end + end + protected def method_name_and_suffix(method_name) diff --git a/spec/hashie/mash_spec.rb b/spec/hashie/mash_spec.rb index 3bcb478..837a7f1 100644 --- a/spec/hashie/mash_spec.rb +++ b/spec/hashie/mash_spec.rb @@ -878,6 +878,90 @@ describe Hashie::Mash do end end + describe '#compact' do + subject(:mash) { described_class.new(a: 1, b: nil) } + + it 'returns a Hashie::Mash' do + expect(mash.compact).to be_kind_of(described_class) + end + + it 'removes keys with nil values' do + expect(mash.compact).to eq('a' => 1) + end + + context 'when using with subclass' do + let(:subclass) { Class.new(Hashie::Mash) } + subject(:sub_mash) { subclass.new(a: 1, b: nil) } + + it 'creates an instance of subclass' do + expect(sub_mash.compact).to be_kind_of(subclass) + end + end + end + + describe '#invert' do + subject(:mash) { described_class.new(a: 'apple', b: 4) } + + it 'returns a Hashie::Mash' do + expect(mash.invert).to be_kind_of(described_class) + end + + it 'returns a mash with the keys and values inverted' do + expect(mash.invert).to eq('apple' => 'a', '4' => 'b') + end + + context 'when using with subclass' do + let(:subclass) { Class.new(Hashie::Mash) } + subject(:sub_mash) { subclass.new(a: 1, b: nil) } + + it 'creates an instance of subclass' do + expect(sub_mash.invert).to be_kind_of(subclass) + end + end + end + + describe '#reject' do + subject(:mash) { described_class.new(a: 1, b: nil) } + + it 'returns a Hashie::Mash' do + expect(mash.reject { |_k, v| v.nil? }).to be_kind_of(described_class) + end + + it 'rejects keys for which the block returns true' do + expect(mash.reject { |_k, v| v.nil? }).to eq('a' => 1) + end + + context 'when using with subclass' do + let(:subclass) { Class.new(Hashie::Mash) } + subject(:sub_mash) { subclass.new(a: 1, b: nil) } + + it 'creates an instance of subclass' do + expect(sub_mash.reject { |_k, v| v.nil? }).to be_kind_of(subclass) + end + end + end + + describe '#select' do + subject(:mash) { described_class.new(a: 'apple', b: 4) } + + it 'returns a Hashie::Mash' do + expect(mash.select { |_k, v| v.is_a? String }).to be_kind_of(described_class) + end + + it 'selects keys for which the block returns true' do + expect(mash.select { |_k, v| v.is_a? String }).to eq('a' => 'apple') + end + + context 'when using with subclass' do + let(:subclass) { Class.new(Hashie::Mash) } + subject(:sub_mash) { subclass.new(a: 1, b: nil) } + + it 'creates an instance of subclass' do + expect(sub_mash.select { |_k, v| v.is_a? String }).to be_kind_of(subclass) + end + end + end + with_minimum_ruby('2.3.0') do describe '#dig' do subject { described_class.new(a: { b: 1 }) } @@ -895,4 +979,71 @@ describe Hashie::Mash do end end end + + with_minimum_ruby('2.4.0') do + 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 '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 } } + + it 'creates an instance of subclass' do + expect(sub_mash).to be_kind_of(subclass) + end + end + end + end + + with_minimum_ruby('2.5.0') do + describe '#slice' do + subject(:mash) { described_class.new(a: 1, b: 2) } + + it 'returns a Hashie::Mash' do + expect(mash.slice(:a)).to be_kind_of(described_class) + end + + it 'returns a Mash with only the keys passed' do + expect(mash.slice(:a).to_hash).to eq('a' => 1) + end + + context 'when using with subclass' do + let(:subclass) { Class.new(Hashie::Mash) } + subject(:sub_mash) { subclass.new(a: 1, b: 2) } + + it 'creates an instance of subclass' do + expect(sub_mash.slice(:a)).to be_kind_of(subclass) + end + end + end + + describe '#transform_keys' do + subject(:mash) { described_class.new(a: 1, b: 2) } + + it 'returns a Hashie::Mash' do + expect(mash.transform_keys { |k| k + k }).to be_kind_of(described_class) + end + + it 'returns a Mash with transformed keys' do + expect(mash.transform_keys { |k| k + k }).to eq('aa' => 1, 'bb' => 2) + end + + context 'when using with subclass' do + let(:subclass) { Class.new(Hashie::Mash) } + subject(:sub_mash) { subclass.new(a: 1, b: 2) } + + it 'creates an instance of subclass' do + expect(sub_mash.transform_keys { |k| k + k }).to be_kind_of(subclass) + end + end + end + end end |