summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Lincoln <max@devopsy.com>2014-08-14 17:00:16 -0400
committerMax Lincoln <max@devopsy.com>2014-08-14 17:00:16 -0400
commit68b83a8e283079d702fb9cf3f1bea9a6b7af2b16 (patch)
treeba12f72527347b7d1136b874b3dfc43839110ed6
parent555c1b9273b9af9d61fefabf185f6ae662e1a2d5 (diff)
downloadhashie-68b83a8e283079d702fb9cf3f1bea9a6b7af2b16.tar.gz
Error handling, test showing SystemStackError
-rw-r--r--lib/hashie/extensions/coercion.rb27
-rw-r--r--spec/hashie/extensions/coercion_spec.rb43
2 files changed, 57 insertions, 13 deletions
diff --git a/lib/hashie/extensions/coercion.rb b/lib/hashie/extensions/coercion.rb
index d156b09..332953f 100644
--- a/lib/hashie/extensions/coercion.rb
+++ b/lib/hashie/extensions/coercion.rb
@@ -1,6 +1,9 @@
module Hashie
module Extensions
module Coercion
+ class CoercionError < StandardError
+ end
+
CORE_TYPES = {
Integer => :to_i,
Float => :to_f,
@@ -23,20 +26,22 @@ module Hashie
into = self.class.key_coercion(key) || self.class.value_coercion(value)
return set_value_without_coercion(key, value) unless value && into
- return set_value_without_coercion(key, coerce_or_init(into).call(value)) unless into.is_a?(Enumerable)
-
- if into.class >= Hash
- key_coerce = coerce_or_init(into.flatten[0])
- value_coerce = coerce_or_init(into.flatten[-1])
- value = Hash[value.map { |k, v| [key_coerce.call(k), value_coerce.call(v)] }]
- else # Enumerable but not Hash: Array, Set
- value_coerce = coerce_or_init(into.first)
- value = into.class.new(value.map { |v| value_coerce.call(v) })
+ begin
+ return set_value_without_coercion(key, coerce_or_init(into).call(value)) unless into.is_a?(Enumerable)
+
+ if into.class >= Hash
+ key_coerce = coerce_or_init(into.flatten[0])
+ value_coerce = coerce_or_init(into.flatten[-1])
+ value = Hash[value.map { |k, v| [key_coerce.call(k), value_coerce.call(v)] }]
+ else # Enumerable but not Hash: Array, Set
+ value_coerce = coerce_or_init(into.first)
+ value = into.class.new(value.map { |v| value_coerce.call(v) })
+ end
+ rescue NoMethodError, TypeError => e
+ raise CoercionError, "Cannot coerce property #{key.inspect} from #{value.class} to #{into}: #{e.message}"
end
set_value_without_coercion(key, value)
- rescue NoMethodError, TypeError => e
- raise TypeError, "Cannot coerce property #{key.inspect} from #{value.class} to #{into}: #{e.message}"
end
def coerce_or_init(type)
diff --git a/spec/hashie/extensions/coercion_spec.rb b/spec/hashie/extensions/coercion_spec.rb
index cae8aa8..a4e2332 100644
--- a/spec/hashie/extensions/coercion_spec.rb
+++ b/spec/hashie/extensions/coercion_spec.rb
@@ -36,6 +36,32 @@ describe Hashie::Extensions::Coercion do
let(:instance) { subject.new }
describe '#coerce_key' do
+ context 'nesting' do
+ class RootCoercableHash < Hash
+ include Hashie::Extensions::Coercion
+ include Hashie::Extensions::MergeInitializer
+ coerce_key :foo, Integer
+ end
+
+ class NestedCoercableHash < RootCoercableHash
+ include Hashie::Extensions::Coercion
+ include Hashie::Extensions::MergeInitializer
+ coerce_key :foo, Integer
+ end
+
+ subject { RootCoercableHash }
+ let(:instance) { subject.new }
+
+ it 'coeces nested objects' do
+ subject.coerce_key :nested, NestedCoercableHash
+
+ instance[:nested] = { foo: '123' }
+ expect(instance[:nested]).to be_a(NestedCoercableHash)
+ expect(instance[:nested][:foo]).to be_an(Integer)
+ expect(instance[:nested][:foo]).to eq('123')
+ end
+ end
+
it { expect(subject).to be_respond_to(:coerce_key) }
it 'runs through coerce on a specified key' do
@@ -153,6 +179,19 @@ describe Hashie::Extensions::Coercion do
test_coercion '2/3+3/4i', Complex, :to_c
end
+ it 'coerces collections with core types' do
+ subject.coerce_key :foo, Hash[String => String]
+
+ instance[:foo] = {
+ abc: 123,
+ xyz: 987
+ }
+ expect(instance[:foo]).to eq(
+ 'abc' => '123',
+ 'xyz' => '987'
+ )
+ end
+
it 'can coerce booleans via a proc' do
subject.coerce_key :foo, ->(v) do
case v
@@ -180,7 +219,7 @@ describe Hashie::Extensions::Coercion do
it 'raises errors for non-coercable types' do
subject.coerce_key :foo, NotInitializable
- expect { instance[:foo] = 'true' }.to raise_error(TypeError, /NotInitializable is not a coercable type/)
+ expect { instance[:foo] = 'true' }.to raise_error(Hashie::Extensions::Coercion::CoercionError, /NotInitializable is not a coercable type/)
end
pending 'can coerce false' do
@@ -382,7 +421,7 @@ describe Hashie::Extensions::Coercion do
it 'raises a TypeError when coercion is not possible' do
subject.coerce_value Fixnum, Symbol
- expect { instance[:hi] = 1 }.to raise_error(TypeError, /Cannot coerce property :hi from Fixnum to Symbol/)
+ expect { instance[:hi] = 1 }.to raise_error(Hashie::Extensions::Coercion::CoercionError, /Cannot coerce property :hi from Fixnum to Symbol/)
end
pending 'coerces Integer to String' do