summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Lincoln <max@devopsy.com>2014-08-14 19:21:16 -0400
committerMax Lincoln <max@devopsy.com>2014-08-14 19:25:24 -0400
commitc4957c6ff9754b88499633bf2cdcfdea19320670 (patch)
tree990c3c932680dd6c5dba85b54d253c134d5ac8ff
parent68b83a8e283079d702fb9cf3f1bea9a6b7af2b16 (diff)
downloadhashie-c4957c6ff9754b88499633bf2cdcfdea19320670.tar.gz
core type coercion may be done!
-rw-r--r--lib/hashie/extensions/coercion.rb14
-rw-r--r--spec/hashie/extensions/coercion_spec.rb99
2 files changed, 84 insertions, 29 deletions
diff --git a/lib/hashie/extensions/coercion.rb b/lib/hashie/extensions/coercion.rb
index 332953f..cc96dd0 100644
--- a/lib/hashie/extensions/coercion.rb
+++ b/lib/hashie/extensions/coercion.rb
@@ -13,6 +13,11 @@ module Hashie
Symbol => :to_sym
}
+ ABSTRACT_CORE_TYPES = {
+ Integer => [Fixnum, Bignum],
+ Numeric => [Fixnum, Bignum, Float, Complex, Rational]
+ }
+
def self.included(base)
base.send :include, InstanceMethods
base.extend ClassMethods # NOTE: we wanna make sure we first define set_value_with_coercion before extending
@@ -25,7 +30,8 @@ module Hashie
def set_value_with_coercion(key, value)
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, value) if value.nil? || into.nil?
+
begin
return set_value_without_coercion(key, coerce_or_init(into).call(value)) unless into.is_a?(Enumerable)
@@ -137,6 +143,12 @@ module Hashie
def coerce_value(from, into, options = {})
options = { strict: true }.merge(options)
+ if ABSTRACT_CORE_TYPES.key? from
+ ABSTRACT_CORE_TYPES[from].each do | type |
+ coerce_value type, into, options
+ end
+ end
+
if options[:strict]
(@strict_value_coercions ||= {})[from] = into
else
diff --git a/spec/hashie/extensions/coercion_spec.rb b/spec/hashie/extensions/coercion_spec.rb
index a4e2332..0ba4abf 100644
--- a/spec/hashie/extensions/coercion_spec.rb
+++ b/spec/hashie/extensions/coercion_spec.rb
@@ -8,13 +8,13 @@ describe Hashie::Extensions::Coercion do
class Initializable
attr_reader :coerced, :value
- def initialize(obj, coerced = false)
+ def initialize(obj, coerced = nil)
@coerced = coerced
@value = obj.class.to_s
end
def coerced?
- !!@coerced
+ !@coerced.nil?
end
end
@@ -37,28 +37,61 @@ describe Hashie::Extensions::Coercion do
describe '#coerce_key' do
context 'nesting' do
- class RootCoercableHash < Hash
+ class BaseCoercableHash < 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
+ class NestedCoercableHash < BaseCoercableHash
+ coerce_key :foo, String
+ coerce_key :bar, Integer
+ end
+
+ class RootCoercableHash < BaseCoercableHash
+ coerce_key :nested, NestedCoercableHash
+ coerce_key :nested_list, Array[NestedCoercableHash]
+ coerce_key :nested_hash, Hash[String => NestedCoercableHash]
+ end
+
+ def test_nested_object(obj)
+ expect(obj).to be_a(NestedCoercableHash)
+ expect(obj[:foo]).to be_a(String)
+ expect(obj[:bar]).to be_an(Integer)
end
subject { RootCoercableHash }
let(:instance) { subject.new }
it 'coeces nested objects' do
- subject.coerce_key :nested, NestedCoercableHash
+ instance[:nested] = { foo: 123, bar: '456' }
+ test_nested_object(instance[:nested])
+ end
+
+ it 'coeces nested arrays' do
+ instance[:nested_list] = [
+ { foo: 123, bar: '456' },
+ { foo: 234, bar: '567' },
+ { foo: 345, bar: '678' }
+ ]
+ expect(instance[:nested_list]).to be_a Array
+ expect(instance[:nested_list].size).to eq(3)
+ instance[:nested_list].each do | nested |
+ test_nested_object nested
+ end
+ end
- 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')
+ it 'coeces nested hashes' do
+ instance[:nested_hash] = {
+ a: { foo: 123, bar: '456' },
+ b: { foo: 234, bar: '567' },
+ c: { foo: 345, bar: '678' }
+ }
+ expect(instance[:nested_hash]).to be_a Hash
+ expect(instance[:nested_hash].size).to eq(3)
+ instance[:nested_hash].each do | key, nested |
+ expect(key).to be_a(String)
+ test_nested_object nested
+ end
end
end
@@ -222,20 +255,20 @@ describe Hashie::Extensions::Coercion do
expect { instance[:foo] = 'true' }.to raise_error(Hashie::Extensions::Coercion::CoercionError, /NotInitializable is not a coercable type/)
end
- pending 'can coerce false' do
- subject.coerce_key :foo, Initializable
+ it 'can coerce false' do
+ subject.coerce_key :foo, Coercable
instance[:foo] = false
expect(instance[:foo]).to be_coerced
- expect(instance[:foo].value).to eq(false)
+ expect(instance[:foo].value).to eq('FalseClass')
end
- pending 'can coerce nil' do
- subject.coerce_key :foo, Initializable
+ it 'does not coerce nil' do
+ subject.coerce_key :foo, String
instance[:foo] = nil
- expect(instance[:foo]).to be_coerced
- expect(instance[:foo].value).to be_nil
+ expect(instance[:foo]).to_not eq('')
+ expect(instance[:foo]).to be_nil
end
end
@@ -424,18 +457,28 @@ describe Hashie::Extensions::Coercion do
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
+ it 'coerces Integer to String' do
subject.coerce_value Integer, String
- instance[:foo] = 2
- instance[:bar] = 2.7
- expect(instance[:foo]).to be_a(String)
- expect(instance[:foo]).to eq('2')
- expect(instance[:bar]).to be_a(String)
- expect(instance[:bar]).to eq('2.0')
+ {
+ fixnum: 2,
+ bignum: 12_345_667_890_987_654_321,
+ float: 2.7,
+ rational: Rational(2, 3),
+ complex: Complex(1)
+ }.each do | k, v |
+ instance[k] = v
+ if v.is_a? Integer
+ expect(instance[k]).to be_a(String)
+ expect(instance[k]).to eq(v.to_s)
+ else
+ expect(instance[k]).to_not be_a(String)
+ expect(instance[k]).to eq(v)
+ end
+ end
end
- pending 'coerces Numeric to String' do
+ it 'coerces Numeric to String' do
subject.coerce_value Numeric, String
{