Skip to content

Commit

Permalink
Data-mapped instances can now be converted to Hash with #to_hash method.
Browse files Browse the repository at this point in the history
  • Loading branch information
tszolar committed May 28, 2014
1 parent d41dc29 commit 37163bd
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 6 deletions.
1 change: 1 addition & 0 deletions lib/kosapi_client.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require 'active_support/core_ext/hash/keys'
require 'active_support/core_ext/hash/reverse_merge'
require 'active_support/inflector'
require 'uri_template'

Expand Down
33 changes: 28 additions & 5 deletions lib/kosapi_client/entity/data_mappings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,37 @@ def self.included(base)
base.extend(ClassMethods)
end

def to_hash
result = {}
self.class.attr_mappings.each_key { |k| result[k] = convert_value(send(k)) }
result
end

private
def convert_value(val)
if val.respond_to? :to_hash
val.to_hash
elsif val.is_a?(Array)
val.map { |it| convert_value(it) }
else
val
end
end

module ClassMethods

def map_data(name, type=String, opts = {})
attr_accessor name
opts[:type] = type
@@data_mappings ||= {}
@@data_mappings[self] ||= {}
@@data_mappings[self][name] = opts
@data_mappings ||= {}
@data_mappings[name] = opts
end

def attr_mappings
if self.superclass.respond_to? :attr_mappings
parent_mappings = self.superclass.attr_mappings
end
@data_mappings.reverse_merge(parent_mappings || {})
end

# Parses composed domain type from hash response structure.
Expand All @@ -33,8 +56,8 @@ def set_mapped_attributes(instance, source_hash)
if self.superclass.respond_to? :set_mapped_attributes
self.superclass.set_mapped_attributes(instance, source_hash)
end
raise "Missing data mappings for entity #{self}" unless @@data_mappings[self]
@@data_mappings[self].each do |name, options|
raise "Missing data mappings for entity #{self}" unless @data_mappings
@data_mappings.each do |name, options|
set_mapped_attribute(instance, name, source_hash, options)
end
end
Expand Down
63 changes: 62 additions & 1 deletion spec/kosapi_client/entity/data_mappings_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
describe KOSapiClient::Entity::DataMappings do

let(:dummy_class) { Class.new { include KOSapiClient::Entity::DataMappings } }
let(:derived_class) { Class.new(dummy_class) }
let(:dummy_instance) { dummy_class.new }

it 'defines .parse class method' do
Expand All @@ -15,7 +16,7 @@

describe '.parse' do

it 'parses simple hash structure' do
it 'parses to string by default' do
dummy_class.map_data :foo
parsed = dummy_class.parse({foo: 'bar'})
expect(parsed).to be_an_instance_of(dummy_class)
Expand Down Expand Up @@ -58,4 +59,64 @@

end

describe '.map_data' do

it 'maps parent attributes' do
dummy_class.map_data :foo
derived_class.map_data :bar
instance = derived_class.parse({foo: '123', bar: '456'})
expect(instance).to respond_to(:foo, :bar)
end

it 'does not map child attributes' do
dummy_class.map_data :foo
derived_class.map_data :bar
instance = dummy_class.parse({foo: '123', bar: '456'})
expect(instance).to respond_to(:foo)
expect(instance).not_to respond_to(:bar)
end

end

describe '#to_hash' do

it 'converts mapped attributes to a hash' do
dummy_class.map_data :foo
instance = dummy_class.parse({foo: 'bar'})
expect(instance.to_hash).to eq({foo: 'bar'})
end

it 'converts class hierarchy attributes to a hash' do
dummy_class.map_data :foo
derived_class.map_data :bar
instance = derived_class.parse({foo: '123', bar: '456'})
expect(instance.to_hash).to eq({foo: '123', bar: '456'})
end

it 'converts array to a hash' do
dummy_class.map_data :foo, [Integer]
instance = dummy_class.parse({foo: %w(123 456)})
expect(instance.to_hash).to eq({foo: [123, 456]})
end

it 'converts nested instances' do
dummy_class.map_data :foo
instance = dummy_class.new()
instance2 = dummy_class.new()
instance.foo = instance2
instance2.foo = 'bar'
expect(instance.to_hash).to eq({foo: {foo: 'bar'}})
end

it 'converts array of nested instances' do
dummy_class.map_data :foo
instance = dummy_class.new()
instance2 = dummy_class.new()
instance.foo = [instance2]
instance2.foo = 'bar'
expect(instance.to_hash).to eq({foo: [{foo: 'bar'}]})
end

end

end

0 comments on commit 37163bd

Please sign in to comment.