Fix except use in Mash#load (#508)
This commit is contained in:
parent
d2071d82a2
commit
25fe2f747e
|
@ -28,6 +28,7 @@ matrix:
|
|||
dist: bionic
|
||||
- rvm: rbx-3
|
||||
dist: trusty
|
||||
bundler_args: --retry 0
|
||||
- rvm: jruby-9.0.5.0
|
||||
dist: trusty
|
||||
- rvm: jruby-head
|
||||
|
|
|
@ -32,6 +32,8 @@ scheme are considered to be bugs.
|
|||
* [#467](https://github.com/intridea/hashie/pull/467): Fixed `DeepMerge#deep_merge` mutating nested values within the receiver - [@michaelherold](https://github.com/michaelherold).
|
||||
* [#505](https://github.com/hashie/hashie/pull/505): Ensure that `Hashie::Array`s are not deconverted within `Hashie::Mash`es to make `Mash#dig` work properly - [@michaelherold](https://github.com/michaelherold).
|
||||
* [#507](https://github.com/hashie/hashie/pull/507): Suppress `Psych.safe_load` arg warn when using Psych 3.1.0+ - [@koic](https://github.com/koic).
|
||||
* [#508](https://github.com/hashie/hashie/pull/508): Fixed `Mash.load` no longer uses Rails-only `#except` - [@bobbymcwho](https://github.com/bobbymcwho).
|
||||
* [#508](https://github.com/hashie/hashie/pull/508): Fixed `Hashie::Extensions::DeepMerge` `#deep_merge` not correctly dup'ing sub-hashes if active_support hash extensions were not present - [@bobbymcwho](https://github.com/bobbymcwho).
|
||||
* [#510](https://github.com/hashie/hashie/pull/510): Ensure that `Hashie::Mash#compact` is only defined on Ruby version >= 2.4.0 - [@bobbymcwho](https://github.com/bobbymcwho).
|
||||
* Your contribution here.
|
||||
|
||||
|
|
|
@ -38,6 +38,8 @@ module Hashie
|
|||
hash[k] =
|
||||
if hash.key?(k) && hash[k].is_a?(::Hash) && v.is_a?(::Hash)
|
||||
_recursive_merge(hash[k], v, &block)
|
||||
elsif v.is_a?(::Hash)
|
||||
_recursive_merge({}, v, &block)
|
||||
elsif hash.key?(k) && block_given?
|
||||
yield(k, hash[k], v)
|
||||
else
|
||||
|
|
|
@ -74,8 +74,9 @@ module Hashie
|
|||
return @_mashes[path] if @_mashes.key?(path)
|
||||
raise ArgumentError, "The following file doesn't exist: #{path}" unless File.file?(path)
|
||||
|
||||
parser = options.fetch(:parser) { Hashie::Extensions::Parsers::YamlErbParser }
|
||||
@_mashes[path] = new(parser.perform(path, options.except(:parser))).freeze
|
||||
options = options.dup
|
||||
parser = options.delete(:parser) { Hashie::Extensions::Parsers::YamlErbParser }
|
||||
@_mashes[path] = new(parser.perform(path, options)).freeze
|
||||
end
|
||||
|
||||
def to_module(mash_method_name = :settings)
|
||||
|
|
|
@ -56,9 +56,9 @@ class DeferredWithSelfTest < Hashie::Dash
|
|||
end
|
||||
|
||||
describe DashTestDefaultProc do
|
||||
it 'as_json behaves correctly with default proc' do
|
||||
it 'to_json behaves correctly with default proc' do
|
||||
object = described_class.new
|
||||
expect(object.as_json).to be == { 'fields' => [] }
|
||||
expect(object.to_json).to be == '{"fields":[]}'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
require 'spec_helper'
|
||||
require 'active_support/core_ext/hash/indifferent_access'
|
||||
|
||||
describe Hashie::Extensions::DeepFind do
|
||||
subject { Class.new(Hash) { include Hashie::Extensions::DeepFind } }
|
||||
|
@ -71,41 +70,6 @@ describe Hashie::Extensions::DeepFind do
|
|||
end
|
||||
end
|
||||
|
||||
context 'on an ActiveSupport::HashWithIndifferentAccess' do
|
||||
subject(:instance) { hash.with_indifferent_access.extend(Hashie::Extensions::DeepFind) }
|
||||
|
||||
describe '#deep_find' do
|
||||
it 'indifferently detects a value from a nested hash' do
|
||||
expect(instance.deep_find(:address)).to eq('123 Library St.')
|
||||
expect(instance.deep_find('address')).to eq('123 Library St.')
|
||||
end
|
||||
|
||||
it 'indifferently detects a value from a nested array' do
|
||||
expect(instance.deep_find(:title)).to eq('Call of the Wild')
|
||||
expect(instance.deep_find('title')).to eq('Call of the Wild')
|
||||
end
|
||||
|
||||
it 'indifferently returns nil if it does not find a match' do
|
||||
expect(instance.deep_find(:wahoo)).to be_nil
|
||||
expect(instance.deep_find('wahoo')).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe '#deep_find_all' do
|
||||
it 'indifferently detects all values from a nested hash' do
|
||||
expect(instance.deep_find_all(:title))
|
||||
.to eq(['Call of the Wild', 'Moby Dick', 'Main Library'])
|
||||
expect(instance.deep_find_all('title'))
|
||||
.to eq(['Call of the Wild', 'Moby Dick', 'Main Library'])
|
||||
end
|
||||
|
||||
it 'indifferently returns nil if it does not find any matches' do
|
||||
expect(instance.deep_find_all(:wahoo)).to be_nil
|
||||
expect(instance.deep_find_all('wahoo')).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'on a Hash including Hashie::Extensions::IndifferentAccess' do
|
||||
let(:klass) { Class.new(Hash) { include Hashie::Extensions::IndifferentAccess } }
|
||||
subject(:instance) { klass[hash.dup].extend(Hashie::Extensions::DeepFind) }
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
require 'spec_helper'
|
||||
require 'active_support/core_ext/hash/indifferent_access'
|
||||
|
||||
describe Hashie::Extensions::DeepLocate do
|
||||
let(:hash) do
|
||||
|
@ -123,16 +122,4 @@ describe Hashie::Extensions::DeepLocate do
|
|||
expect(instance.deep_locate(:bool)).to eq([hash[:query]])
|
||||
end
|
||||
end
|
||||
|
||||
context 'on an ActiveSupport::HashWithIndifferentAccess' do
|
||||
let(:instance) { hash.dup.with_indifferent_access }
|
||||
|
||||
it 'can locate symbolic keys' do
|
||||
expect(described_class.deep_locate(:lsr10, instance)).to eq ['lsr10' => { 'gte' => 2014 }]
|
||||
end
|
||||
|
||||
it 'can locate string keys' do
|
||||
expect(described_class.deep_locate('lsr10', instance)).to eq ['lsr10' => { 'gte' => 2014 }]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,208 +0,0 @@
|
|||
# This set of tests verifies that Hashie::Extensions::IndifferentAccess works with
|
||||
# ActiveSupport HashWithIndifferentAccess hashes. See #164 and #166 for details.
|
||||
|
||||
require 'active_support/hash_with_indifferent_access'
|
||||
require 'active_support/core_ext/hash'
|
||||
require 'spec_helper'
|
||||
|
||||
describe Hashie::Extensions::IndifferentAccess do
|
||||
class IndifferentHashWithMergeInitializer < Hash
|
||||
include Hashie::Extensions::MergeInitializer
|
||||
include Hashie::Extensions::IndifferentAccess
|
||||
|
||||
class << self
|
||||
alias build new
|
||||
end
|
||||
end
|
||||
|
||||
class IndifferentHashWithArrayInitializer < Hash
|
||||
include Hashie::Extensions::IndifferentAccess
|
||||
|
||||
class << self
|
||||
alias build []
|
||||
end
|
||||
end
|
||||
|
||||
class IndifferentHashWithTryConvertInitializer < Hash
|
||||
include Hashie::Extensions::IndifferentAccess
|
||||
|
||||
class << self
|
||||
alias build try_convert
|
||||
end
|
||||
end
|
||||
|
||||
class CoercableHash < Hash
|
||||
include Hashie::Extensions::Coercion
|
||||
include Hashie::Extensions::MergeInitializer
|
||||
end
|
||||
|
||||
class MashWithIndifferentAccess < Hashie::Mash
|
||||
include Hashie::Extensions::IndifferentAccess
|
||||
end
|
||||
|
||||
shared_examples_for 'hash with indifferent access' do
|
||||
it 'is able to access via string or symbol' do
|
||||
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(abc: 123)
|
||||
h = subject.build(indifferent_hash)
|
||||
expect(h[:abc]).to eq 123
|
||||
expect(h['abc']).to eq 123
|
||||
end
|
||||
|
||||
describe '#values_at' do
|
||||
it 'indifferently finds values' do
|
||||
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(
|
||||
:foo => 'bar', 'baz' => 'qux'
|
||||
)
|
||||
h = subject.build(indifferent_hash)
|
||||
expect(h.values_at('foo', :baz)).to eq %w[bar qux]
|
||||
end
|
||||
end
|
||||
|
||||
describe '#fetch' do
|
||||
it 'works like normal fetch, but indifferent' do
|
||||
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
|
||||
h = subject.build(indifferent_hash)
|
||||
expect(h.fetch(:foo)).to eq h.fetch('foo')
|
||||
expect(h.fetch(:foo)).to eq 'bar'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#delete' do
|
||||
it 'deletes indifferently' do
|
||||
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(
|
||||
:foo => 'bar',
|
||||
'baz' => 'qux'
|
||||
)
|
||||
h = subject.build(indifferent_hash)
|
||||
h.delete('foo')
|
||||
h.delete(:baz)
|
||||
expect(h).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
describe '#key?' do
|
||||
let(:h) do
|
||||
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
|
||||
subject.build(indifferent_hash)
|
||||
end
|
||||
|
||||
it 'finds it indifferently' do
|
||||
expect(h).to be_key(:foo)
|
||||
expect(h).to be_key('foo')
|
||||
end
|
||||
|
||||
%w[include? member? has_key?].each do |key_alias|
|
||||
it "is aliased as #{key_alias}" do
|
||||
expect(h.send(key_alias.to_sym, :foo)).to be(true)
|
||||
expect(h.send(key_alias.to_sym, 'foo')).to be(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#update' do
|
||||
let(:h) do
|
||||
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
|
||||
subject.build(indifferent_hash)
|
||||
end
|
||||
|
||||
it 'allows keys to be indifferent still' do
|
||||
h.update(baz: 'qux')
|
||||
expect(h['foo']).to eq 'bar'
|
||||
expect(h['baz']).to eq 'qux'
|
||||
end
|
||||
|
||||
it 'recursively injects indifference into sub-hashes' do
|
||||
h.update(baz: { qux: 'abc' })
|
||||
expect(h['baz']['qux']).to eq 'abc'
|
||||
end
|
||||
|
||||
it 'does not change the ancestors of the injected object class' do
|
||||
h.update(baz: { qux: 'abc' })
|
||||
expect({}).not_to be_respond_to(:indifferent_access?)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#replace' do
|
||||
let(:h) do
|
||||
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
|
||||
subject.build(indifferent_hash).replace(bar: 'baz', hi: 'bye')
|
||||
end
|
||||
|
||||
it 'returns self' do
|
||||
expect(h).to be_a(subject)
|
||||
end
|
||||
|
||||
it 'removes old keys' do
|
||||
[:foo, 'foo'].each do |k|
|
||||
expect(h[k]).to be_nil
|
||||
expect(h.key?(k)).to be_falsy
|
||||
end
|
||||
end
|
||||
|
||||
it 'creates new keys with indifferent access' do
|
||||
[:bar, 'bar', :hi, 'hi'].each { |k| expect(h.key?(k)).to be_truthy }
|
||||
expect(h[:bar]).to eq 'baz'
|
||||
expect(h['bar']).to eq 'baz'
|
||||
expect(h[:hi]).to eq 'bye'
|
||||
expect(h['hi']).to eq 'bye'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#try_convert' do
|
||||
describe 'with conversion' do
|
||||
let(:h) do
|
||||
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
|
||||
subject.try_convert(indifferent_hash)
|
||||
end
|
||||
|
||||
it 'is a subject' do
|
||||
expect(h).to be_a(subject)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'without conversion' do
|
||||
let(:h) { subject.try_convert('{ :foo => bar }') }
|
||||
|
||||
it 'is nil' do
|
||||
expect(h).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with merge initializer' do
|
||||
subject { IndifferentHashWithMergeInitializer }
|
||||
it_should_behave_like 'hash with indifferent access'
|
||||
end
|
||||
|
||||
describe 'with array initializer' do
|
||||
subject { IndifferentHashWithArrayInitializer }
|
||||
it_should_behave_like 'hash with indifferent access'
|
||||
end
|
||||
|
||||
describe 'with try convert initializer' do
|
||||
subject { IndifferentHashWithTryConvertInitializer }
|
||||
it_should_behave_like 'hash with indifferent access'
|
||||
end
|
||||
|
||||
describe 'with coercion' do
|
||||
subject { CoercableHash }
|
||||
|
||||
let(:instance) { subject.new }
|
||||
|
||||
it 'supports coercion for ActiveSupport::HashWithIndifferentAccess' do
|
||||
subject.coerce_key :foo, ActiveSupport::HashWithIndifferentAccess.new(Coercable => Coercable)
|
||||
instance[:foo] = { 'bar_key' => 'bar_value', 'bar2_key' => 'bar2_value' }
|
||||
expect(instance[:foo].keys).to all(be_coerced)
|
||||
expect(instance[:foo].values).to all(be_coerced)
|
||||
expect(instance[:foo]).to be_a(ActiveSupport::HashWithIndifferentAccess)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Mash with indifferent access' do
|
||||
it 'is able to be created for a deep nested HashWithIndifferentAccess' do
|
||||
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(abc: { def: 123 })
|
||||
MashWithIndifferentAccess.new(indifferent_hash)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -147,7 +147,7 @@ describe Hashie::Mash do
|
|||
mash[:test_key] = 'Test value'
|
||||
|
||||
expect { mash[:test_key] = 'A new value' }.not_to raise_error
|
||||
expect(logger_output).to be_blank
|
||||
expect(logger_output).to be_empty
|
||||
end
|
||||
|
||||
it 'does not write to the logger when warnings are disabled' do
|
||||
|
@ -156,7 +156,7 @@ describe Hashie::Mash do
|
|||
end
|
||||
mash_class.new('trust' => { 'two' => 2 })
|
||||
|
||||
expect(logger_output).to be_blank
|
||||
expect(logger_output).to be_empty
|
||||
end
|
||||
|
||||
it 'cannot disable logging on the base Mash' do
|
||||
|
@ -173,7 +173,7 @@ describe Hashie::Mash do
|
|||
|
||||
grandchild_class.new('trust' => { 'two' => 2 })
|
||||
|
||||
expect(logger_output).to be_blank
|
||||
expect(logger_output).to be_empty
|
||||
end
|
||||
|
||||
it 'writes to logger when a key is overridden that is not ignored' do
|
||||
|
@ -182,7 +182,7 @@ describe Hashie::Mash do
|
|||
end
|
||||
|
||||
mash_class.new('address' => { 'zip' => '90210' })
|
||||
expect(logger_output).not_to be_blank
|
||||
expect(logger_output).not_to be_empty
|
||||
end
|
||||
|
||||
it 'does not write to logger when a key is overridden that is ignored' do
|
||||
|
@ -191,7 +191,7 @@ describe Hashie::Mash do
|
|||
end
|
||||
|
||||
mash_class.new('address' => { 'zip' => '90210' })
|
||||
expect(logger_output).to be_blank
|
||||
expect(logger_output).to be_empty
|
||||
end
|
||||
|
||||
it 'carries over the ignored warnings list for warnings on grandchild classes' do
|
||||
|
@ -203,7 +203,7 @@ describe Hashie::Mash do
|
|||
grandchild_class.new('address' => { 'zip' => '90210' }, 'merge' => true)
|
||||
|
||||
expect(grandchild_class.disabled_warnings).to eq(%i[zip merge])
|
||||
expect(logger_output).to be_blank
|
||||
expect(logger_output).to be_empty
|
||||
end
|
||||
|
||||
context 'multiple disable_warnings calls' do
|
||||
|
@ -229,7 +229,7 @@ describe Hashie::Mash do
|
|||
child_class.new('address' => { 'zip' => '90210' }, 'merge' => true, 'cycle' => 'bi')
|
||||
|
||||
expect(child_class.disabled_warnings).to eq([])
|
||||
expect(logger_output).to be_blank
|
||||
expect(logger_output).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -848,18 +848,6 @@ describe Hashie::Mash do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#extractable_options?' do
|
||||
require 'active_support'
|
||||
|
||||
subject { described_class.new(name: 'foo') }
|
||||
let(:args) { [101, 'bar', subject] }
|
||||
|
||||
it 'can be extracted from an array' do
|
||||
expect(args.extract_options!).to eq subject
|
||||
expect(args).to eq [101, 'bar']
|
||||
end
|
||||
end
|
||||
|
||||
describe '#reverse_merge' do
|
||||
subject { described_class.new(a: 1, b: 2) }
|
||||
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
source 'http://rubygems.org'
|
||||
|
||||
gem 'hashie', path: '../../..'
|
||||
require File.expand_path('../../../../lib/hashie/extensions/ruby_version', __FILE__)
|
||||
|
||||
# rubocop:disable Bundler/DuplicatedGem
|
||||
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 'rake'
|
||||
gem 'rspec', '~> 3.5.0'
|
|
@ -0,0 +1,371 @@
|
|||
require 'active_support'
|
||||
require 'active_support/core_ext'
|
||||
require 'active_support/core_ext/hash/indifferent_access'
|
||||
require 'active_support/core_ext/hash'
|
||||
require 'hashie'
|
||||
|
||||
RSpec.configure do |config|
|
||||
config.expect_with :rspec do |expect|
|
||||
expect.syntax = :expect
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.describe Hashie::Mash do
|
||||
describe '#extractable_options?' do
|
||||
subject { Hashie::Mash.new(name: 'foo') }
|
||||
let(:args) { [101, 'bar', subject] }
|
||||
|
||||
it 'can be extracted from an array' do
|
||||
expect(args.extract_options!).to eq subject
|
||||
expect(args).to eq [101, 'bar']
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.describe Hashie::Extensions::DeepFind do
|
||||
let(:hash) do
|
||||
{
|
||||
library: {
|
||||
books: [
|
||||
{ title: 'Call of the Wild' },
|
||||
{ title: 'Moby Dick' }
|
||||
],
|
||||
shelves: nil,
|
||||
location: {
|
||||
address: '123 Library St.',
|
||||
title: 'Main Library'
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
subject(:instance) { hash.with_indifferent_access.extend(Hashie::Extensions::DeepFind) }
|
||||
|
||||
describe '#deep_find' do
|
||||
it 'indifferently detects a value from a nested hash' do
|
||||
expect(instance.deep_find(:address)).to eq('123 Library St.')
|
||||
expect(instance.deep_find('address')).to eq('123 Library St.')
|
||||
end
|
||||
|
||||
it 'indifferently detects a value from a nested array' do
|
||||
expect(instance.deep_find(:title)).to eq('Call of the Wild')
|
||||
expect(instance.deep_find('title')).to eq('Call of the Wild')
|
||||
end
|
||||
|
||||
it 'indifferently returns nil if it does not find a match' do
|
||||
expect(instance.deep_find(:wahoo)).to be_nil
|
||||
expect(instance.deep_find('wahoo')).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe '#deep_find_all' do
|
||||
it 'indifferently detects all values from a nested hash' do
|
||||
expect(instance.deep_find_all(:title))
|
||||
.to eq(['Call of the Wild', 'Moby Dick', 'Main Library'])
|
||||
expect(instance.deep_find_all('title'))
|
||||
.to eq(['Call of the Wild', 'Moby Dick', 'Main Library'])
|
||||
end
|
||||
|
||||
it 'indifferently returns nil if it does not find any matches' do
|
||||
expect(instance.deep_find_all(:wahoo)).to be_nil
|
||||
expect(instance.deep_find_all('wahoo')).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.describe Hashie::Extensions::DeepLocate do
|
||||
let(:hash) do
|
||||
{
|
||||
from: 0,
|
||||
size: 25,
|
||||
query: {
|
||||
bool: {
|
||||
must: [
|
||||
{
|
||||
query_string: {
|
||||
query: 'foobar',
|
||||
default_operator: 'AND',
|
||||
fields: [
|
||||
'title^2',
|
||||
'_all'
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
match: {
|
||||
field_1: 'value_1'
|
||||
}
|
||||
},
|
||||
{
|
||||
range: {
|
||||
lsr09: {
|
||||
gte: 2014
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
should: [
|
||||
{
|
||||
match: {
|
||||
field_2: 'value_2'
|
||||
}
|
||||
}
|
||||
],
|
||||
must_not: [
|
||||
{
|
||||
range: {
|
||||
lsr10: {
|
||||
gte: 2014
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
describe '#deep_locate' do
|
||||
subject(:instance) { hash.with_indifferent_access.extend(described_class) }
|
||||
|
||||
it 'can locate symbolic keys' do
|
||||
expect(described_class.deep_locate(:lsr10, instance)).to eq ['lsr10' => { 'gte' => 2014 }]
|
||||
end
|
||||
|
||||
it 'can locate string keys' do
|
||||
expect(described_class.deep_locate('lsr10', instance)).to eq ['lsr10' => { 'gte' => 2014 }]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.describe Hashie::Extensions::IndifferentAccess do
|
||||
class Initializable
|
||||
attr_reader :coerced, :value
|
||||
|
||||
def initialize(obj, coerced = nil)
|
||||
@coerced = coerced
|
||||
@value = obj.class.to_s
|
||||
end
|
||||
|
||||
def coerced?
|
||||
!@coerced.nil?
|
||||
end
|
||||
end
|
||||
|
||||
class Coercable < Initializable
|
||||
def self.coerce(obj)
|
||||
new(obj, true)
|
||||
end
|
||||
end
|
||||
|
||||
class IndifferentHashWithMergeInitializer < Hash
|
||||
include Hashie::Extensions::MergeInitializer
|
||||
include Hashie::Extensions::IndifferentAccess
|
||||
|
||||
class << self
|
||||
alias build new
|
||||
end
|
||||
end
|
||||
|
||||
class IndifferentHashWithArrayInitializer < Hash
|
||||
include Hashie::Extensions::IndifferentAccess
|
||||
|
||||
class << self
|
||||
alias build []
|
||||
end
|
||||
end
|
||||
|
||||
class IndifferentHashWithTryConvertInitializer < Hash
|
||||
include Hashie::Extensions::IndifferentAccess
|
||||
|
||||
class << self
|
||||
alias build try_convert
|
||||
end
|
||||
end
|
||||
|
||||
class CoercableHash < Hash
|
||||
include Hashie::Extensions::Coercion
|
||||
include Hashie::Extensions::MergeInitializer
|
||||
end
|
||||
|
||||
class MashWithIndifferentAccess < Hashie::Mash
|
||||
include Hashie::Extensions::IndifferentAccess
|
||||
end
|
||||
|
||||
shared_examples_for 'hash with indifferent access' do
|
||||
it 'is able to access via string or symbol' do
|
||||
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(abc: 123)
|
||||
h = subject.build(indifferent_hash)
|
||||
expect(h[:abc]).to eq 123
|
||||
expect(h['abc']).to eq 123
|
||||
end
|
||||
|
||||
describe '#values_at' do
|
||||
it 'indifferently finds values' do
|
||||
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(
|
||||
:foo => 'bar', 'baz' => 'qux'
|
||||
)
|
||||
h = subject.build(indifferent_hash)
|
||||
expect(h.values_at('foo', :baz)).to eq %w[bar qux]
|
||||
end
|
||||
end
|
||||
|
||||
describe '#fetch' do
|
||||
it 'works like normal fetch, but indifferent' do
|
||||
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
|
||||
h = subject.build(indifferent_hash)
|
||||
expect(h.fetch(:foo)).to eq h.fetch('foo')
|
||||
expect(h.fetch(:foo)).to eq 'bar'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#delete' do
|
||||
it 'deletes indifferently' do
|
||||
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(
|
||||
:foo => 'bar',
|
||||
'baz' => 'qux'
|
||||
)
|
||||
h = subject.build(indifferent_hash)
|
||||
h.delete('foo')
|
||||
h.delete(:baz)
|
||||
expect(h).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
describe '#key?' do
|
||||
let(:h) do
|
||||
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
|
||||
subject.build(indifferent_hash)
|
||||
end
|
||||
|
||||
it 'finds it indifferently' do
|
||||
expect(h).to be_key(:foo)
|
||||
expect(h).to be_key('foo')
|
||||
end
|
||||
|
||||
%w[include? member? has_key?].each do |key_alias|
|
||||
it "is aliased as #{key_alias}" do
|
||||
expect(h.send(key_alias.to_sym, :foo)).to be(true)
|
||||
expect(h.send(key_alias.to_sym, 'foo')).to be(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#update' do
|
||||
let(:h) do
|
||||
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
|
||||
subject.build(indifferent_hash)
|
||||
end
|
||||
|
||||
it 'allows keys to be indifferent still' do
|
||||
h.update(baz: 'qux')
|
||||
expect(h['foo']).to eq 'bar'
|
||||
expect(h['baz']).to eq 'qux'
|
||||
end
|
||||
|
||||
it 'recursively injects indifference into sub-hashes' do
|
||||
h.update(baz: { qux: 'abc' })
|
||||
expect(h['baz']['qux']).to eq 'abc'
|
||||
end
|
||||
|
||||
it 'does not change the ancestors of the injected object class' do
|
||||
h.update(baz: { qux: 'abc' })
|
||||
expect({}).not_to be_respond_to(:indifferent_access?)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#replace' do
|
||||
let(:h) do
|
||||
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
|
||||
subject.build(indifferent_hash).replace(bar: 'baz', hi: 'bye')
|
||||
end
|
||||
|
||||
it 'returns self' do
|
||||
expect(h).to be_a(subject)
|
||||
end
|
||||
|
||||
it 'removes old keys' do
|
||||
[:foo, 'foo'].each do |k|
|
||||
expect(h[k]).to be_nil
|
||||
expect(h.key?(k)).to be_falsy
|
||||
end
|
||||
end
|
||||
|
||||
it 'creates new keys with indifferent access' do
|
||||
[:bar, 'bar', :hi, 'hi'].each { |k| expect(h.key?(k)).to be_truthy }
|
||||
expect(h[:bar]).to eq 'baz'
|
||||
expect(h['bar']).to eq 'baz'
|
||||
expect(h[:hi]).to eq 'bye'
|
||||
expect(h['hi']).to eq 'bye'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#try_convert' do
|
||||
describe 'with conversion' do
|
||||
let(:h) do
|
||||
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
|
||||
subject.try_convert(indifferent_hash)
|
||||
end
|
||||
|
||||
it 'is a subject' do
|
||||
expect(h).to be_a(subject)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'without conversion' do
|
||||
let(:h) { subject.try_convert('{ :foo => bar }') }
|
||||
|
||||
it 'is nil' do
|
||||
expect(h).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with merge initializer' do
|
||||
subject { IndifferentHashWithMergeInitializer }
|
||||
it_should_behave_like 'hash with indifferent access'
|
||||
end
|
||||
|
||||
describe 'with array initializer' do
|
||||
subject { IndifferentHashWithArrayInitializer }
|
||||
it_should_behave_like 'hash with indifferent access'
|
||||
end
|
||||
|
||||
describe 'with try convert initializer' do
|
||||
subject { IndifferentHashWithTryConvertInitializer }
|
||||
it_should_behave_like 'hash with indifferent access'
|
||||
end
|
||||
|
||||
describe 'with coercion' do
|
||||
subject { CoercableHash }
|
||||
|
||||
let(:instance) { subject.new }
|
||||
|
||||
it 'supports coercion for ActiveSupport::HashWithIndifferentAccess' do
|
||||
subject.coerce_key :foo, ActiveSupport::HashWithIndifferentAccess.new(Coercable => Coercable)
|
||||
instance[:foo] = { 'bar_key' => 'bar_value', 'bar2_key' => 'bar2_value' }
|
||||
expect(instance[:foo].keys).to all(be_coerced)
|
||||
expect(instance[:foo].values).to all(be_coerced)
|
||||
expect(instance[:foo]).to be_a(ActiveSupport::HashWithIndifferentAccess)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Mash with indifferent access' do
|
||||
it 'is able to be created for a deep nested HashWithIndifferentAccess' do
|
||||
indifferent_hash = ActiveSupport::HashWithIndifferentAccess.new(abc: { def: 123 })
|
||||
MashWithIndifferentAccess.new(indifferent_hash)
|
||||
end
|
||||
end
|
||||
|
||||
class DashTestDefaultProc < Hashie::Dash
|
||||
property :fields, default: -> { [] }
|
||||
end
|
||||
|
||||
describe DashTestDefaultProc do
|
||||
it 'as_json behaves correctly with default proc' do
|
||||
object = described_class.new
|
||||
expect(object.as_json).to be == { 'fields' => [] }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -11,9 +11,6 @@ require 'rspec/pending_for'
|
|||
require './spec/support/ruby_version_check'
|
||||
require './spec/support/logger'
|
||||
|
||||
require 'active_support'
|
||||
require 'active_support/core_ext'
|
||||
|
||||
RSpec.configure do |config|
|
||||
config.extend RubyVersionCheck
|
||||
config.expect_with :rspec do |expect|
|
||||
|
|
Loading…
Reference in New Issue