From a7d57c921dd9a3e99aff95bcae685f831cade7f9 Mon Sep 17 00:00:00 2001 From: Michael Herold Date: Thu, 22 Oct 2020 22:11:34 -0500 Subject: Allow exporting a normal, not-indifferent Hash Following the conventions in `activesupport` and the semantics of the `#to_hash` method in Ruby's standard library, the `#to_hash` method for a hash that has mixed in `IndifferentAccess` will now export the hash as a normal, not-indifferent hash. --- CHANGELOG.md | 1 + README.md | 12 +++++++++ lib/hashie/extensions/indifferent_access.rb | 12 +++++++++ spec/hashie/extensions/indifferent_access_spec.rb | 30 +++++++++++++++++++++++ 4 files changed, 55 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb383a7..abded32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Any violations of this scheme are considered to be bugs. * [#523](https://github.com/hashie/hashie/pull/523): Added TOC, ensure a keep-a-changelog formatted CHANGELOG - [@dblock](https://github.com/dblock). * [#522](https://github.com/hashie/hashie/pull/522): Added eierlegende Wollmilchsau mascot graphic - [@carolineartz](https://github.com/carolineartz). * [#530](https://github.com/hashie/hashie/pull/530): Added Hashie::Extensions::Dash::PredefinedValues - [@caalberts](https://github.com/caalberts). +* [#536](https://github.com/hashie/hashie/pull/536): Added exporting a normal Hash from an indifferent one through the `#to_hash` method - [@michaelherold](https://github.com/michaelherold). * Your contribution here. ### Changed diff --git a/README.md b/README.md index b3b934f..47608f6 100644 --- a/README.md +++ b/README.md @@ -333,6 +333,18 @@ myhash['fishes'][:food] = 'flakes' myhash['fishes']['food'] # => "flakes" ``` +To get back a normal, not-indifferent Hash, you can use `#to_hash` on the indifferent hash. It exports the keys as strings, not symbols: + +```ruby +myhash = MyHash.new +myhash["foo"] = "bar" +myhash[:foo] #=> "bar" + +normal_hash = myhash.to_hash +myhash["foo"] #=> "bar" +myhash[:foo] #=> nil +``` + ### IgnoreUndeclared This extension can be mixed in to silently ignore undeclared properties on initialization instead of raising an error. This is useful when using a Trash to capture a subset of a larger hash. diff --git a/lib/hashie/extensions/indifferent_access.rb b/lib/hashie/extensions/indifferent_access.rb index ebdb0f9..d6b9da3 100644 --- a/lib/hashie/extensions/indifferent_access.rb +++ b/lib/hashie/extensions/indifferent_access.rb @@ -143,6 +143,18 @@ module Hashie super.convert! end + def to_hash + {}.tap do |result| + each_pair { |key, value| result[key] = value } + + if default_proc + result.default_proc = default_proc + else + result.default = default + end + end + end + with_minimum_ruby('2.5.0') do def slice(*keys) string_keys = keys.map { |key| convert_key(key) } diff --git a/spec/hashie/extensions/indifferent_access_spec.rb b/spec/hashie/extensions/indifferent_access_spec.rb index c48ad0c..0aec787 100644 --- a/spec/hashie/extensions/indifferent_access_spec.rb +++ b/spec/hashie/extensions/indifferent_access_spec.rb @@ -77,6 +77,36 @@ describe Hashie::Extensions::IndifferentAccess do end end + describe '#to_hash' do + let(:indifferent_hash) { Class.new(::Hash) { include Hashie::Extensions::IndifferentAccess } } + + it 'returns a normal hash without indifference' do + indifferent = indifferent_hash.new + indifferent['cat'] = 'meow' + + subject = indifferent.to_hash + + expect(subject['cat']).to eq 'meow' + expect(subject[:cat]).to be_nil + end + + it 'maintains the #default_proc when set' do + indifferent = indifferent_hash.new { |_hash, key| "Nothing here: #{key}" } + + subject = indifferent.to_hash + + expect(subject['babble']).to eq 'Nothing here: babble' + end + + it 'maintains the #default when set' do + indifferent = indifferent_hash.new(0) + + subject = indifferent.to_hash + + expect(subject['babble']).to eq 0 + end + end + describe 'when included in dash' do let(:params) { { foo: 'bar' } } subject { IndifferentHashWithDash.new(params) } -- cgit v1.2.1