summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBobby McDonald <BobbyMcWho@users.noreply.github.com>2020-01-14 08:50:43 -0500
committerDaniel Doubrovkine (dB.) @dblockdotorg <dblock@dblock.org>2020-01-14 08:50:43 -0500
commit25fe2f747ee06e563808e08493ec7a471cc82b26 (patch)
tree131c87eb22d54097a58d6011e1a8c5669d7c0f51
parentd2071d82a2ceb2513bc0ff9c827ab3bc2a80b072 (diff)
downloadhashie-25fe2f747ee06e563808e08493ec7a471cc82b26.tar.gz
Fix except use in Mash#load (#508)
-rw-r--r--.travis.yml1
-rw-r--r--CHANGELOG.md2
-rw-r--r--lib/hashie/extensions/deep_merge.rb2
-rw-r--r--lib/hashie/mash.rb5
-rw-r--r--spec/hashie/dash_spec.rb4
-rw-r--r--spec/hashie/extensions/deep_find_spec.rb36
-rw-r--r--spec/hashie/extensions/deep_locate_spec.rb13
-rw-r--r--spec/hashie/extensions/indifferent_access_with_rails_hwia_spec.rb208
-rw-r--r--spec/hashie/mash_spec.rb26
-rw-r--r--spec/integration/active_support/Gemfile15
-rw-r--r--spec/integration/active_support/integration_spec.rb371
-rw-r--r--spec/spec_helper.rb3
12 files changed, 403 insertions, 283 deletions
diff --git a/.travis.yml b/.travis.yml
index 17f14c1..a78ca26 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -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
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 665e6c4..2f5c487 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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.
diff --git a/lib/hashie/extensions/deep_merge.rb b/lib/hashie/extensions/deep_merge.rb
index 1890e8f..24fa679 100644
--- a/lib/hashie/extensions/deep_merge.rb
+++ b/lib/hashie/extensions/deep_merge.rb
@@ -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
diff --git a/lib/hashie/mash.rb b/lib/hashie/mash.rb
index 658aded..97f75d5 100644
--- a/lib/hashie/mash.rb
+++ b/lib/hashie/mash.rb
@@ -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)
diff --git a/spec/hashie/dash_spec.rb b/spec/hashie/dash_spec.rb
index 5c49026..5f3bfe3 100644
--- a/spec/hashie/dash_spec.rb
+++ b/spec/hashie/dash_spec.rb
@@ -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
diff --git a/spec/hashie/extensions/deep_find_spec.rb b/spec/hashie/extensions/deep_find_spec.rb
index cd13d7f..fddb9d1 100644
--- a/spec/hashie/extensions/deep_find_spec.rb
+++ b/spec/hashie/extensions/deep_find_spec.rb
@@ -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) }
diff --git a/spec/hashie/extensions/deep_locate_spec.rb b/spec/hashie/extensions/deep_locate_spec.rb
index 6c2fcf0..e104e76 100644
--- a/spec/hashie/extensions/deep_locate_spec.rb
+++ b/spec/hashie/extensions/deep_locate_spec.rb
@@ -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
diff --git a/spec/hashie/extensions/indifferent_access_with_rails_hwia_spec.rb b/spec/hashie/extensions/indifferent_access_with_rails_hwia_spec.rb
index c53c531..e69de29 100644
--- a/spec/hashie/extensions/indifferent_access_with_rails_hwia_spec.rb
+++ b/spec/hashie/extensions/indifferent_access_with_rails_hwia_spec.rb
@@ -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
diff --git a/spec/hashie/mash_spec.rb b/spec/hashie/mash_spec.rb
index 603adc0..08e6f09 100644
--- a/spec/hashie/mash_spec.rb
+++ b/spec/hashie/mash_spec.rb
@@ -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) }
diff --git a/spec/integration/active_support/Gemfile b/spec/integration/active_support/Gemfile
new file mode 100644
index 0000000..eee6625
--- /dev/null
+++ b/spec/integration/active_support/Gemfile
@@ -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'
diff --git a/spec/integration/active_support/integration_spec.rb b/spec/integration/active_support/integration_spec.rb
new file mode 100644
index 0000000..e0503c8
--- /dev/null
+++ b/spec/integration/active_support/integration_spec.rb
@@ -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
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index b061f22..dc31d61 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -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|