Browse files

To hash from schema: check if nested values(array, object) reference …

…a schema, if not directly assign them
  • Loading branch information...
1 parent ab34c51 commit 6278fabaf47f7f8ec7ec3a426011fda77e02bcd0 @schorsch schorsch committed Dec 31, 2012
Showing with 77 additions and 5 deletions.
  1. +22 −4 lib/schema_tools/modules/hash.rb
  2. +19 −0 spec/fixtures/lead.json
  3. +36 −1 spec/schema_tools/hash_spec.rb
View
26 lib/schema_tools/modules/hash.rb
@@ -40,7 +40,7 @@ def from_schema(obj, opts={})
fields = opts[:fields]
# get objects class name without inheritance
real_class_name = obj.class.name.split('::').last.underscore
- class_name = opts[:class_name] || real_class_name
+ class_name = opts[:class_name] || real_class_name
# directly return array & hash values
return obj if ['array', 'hash'].include? class_name
@@ -50,19 +50,37 @@ def from_schema(obj, opts={})
# iterate over the defined schema fields
schema['properties'].each do |field, prop|
next if fields && !fields.include?(field)
+
if prop['type'] == 'array'
+
data[field] = [] # always set an empty array
if obj.respond_to?( field ) && rel_objects = obj.send( field )
rel_objects.each do |rel_obj|
- data[field] << from_schema(rel_obj, opts)
+ data[field] << if prop['properties'] && prop['properties']['$ref']
+ #got schema describing the objects
+ from_schema(rel_obj, opts)
+ else
+ rel_obj
+ end
end
end
+
elsif prop['type'] == 'object' # a singular related object
+
data[field] = nil # always set empty val
if obj.respond_to?( field ) && rel_obj = obj.send( field )
- #dont nest field to prevent => client=>{client=>{data} }
- data[field] = from_schema(rel_obj, opts)
+ if prop['properties'] && prop['properties']['$ref']
+ data[field] = from_schema(rel_obj, opts)
+ else
+ # NO recursion directly get values from related object. Does
+ # NOT allow deeper nesting so you MUST define an own schema to be save
+ data[field] = {}
+ prop['properties'].each do |fld, prp|
+ data[field][fld] = rel_obj.send(fld) if obj.respond_to?(field)
+ end
+ end
end
+
else # a simple field is only added if the object knows it
data[field] = obj.send(field) if obj.respond_to?(field)
end
View
19 spec/fixtures/lead.json
@@ -8,6 +8,25 @@
"description": "Where did the person come from",
"type":"string",
"maxLength": 255
+ },
+ "links_clicked":{
+ "description": "Timestamps of clicks. Just an example to test nested array values without object reference",
+ "type":"array",
+ "properties":{
+ "type": "string"
+ }
+ },
+ "conversion":{
+ "description": "Just an example to test nested object value without object reference",
+ "type":"object",
+ "properties":{
+ "from": {
+ "type": "string"
+ },
+ "to": {
+ "type": "string"
+ }
+ }
}
}
}
View
37 spec/schema_tools/hash_spec.rb
@@ -2,7 +2,7 @@
class Client
attr_accessor :first_name, :last_name, :addresses, :id
-end
+ end
describe SchemaTools::Hash do
@@ -41,5 +41,40 @@ class Client
hash['client']['first_name'].should be_nil
end
end
+
+ context 'with plain nested values' do
+
+ class Lead < Client
+ attr_accessor :links_clicked, :conversion
+ end
+
+ class Conversion
+ attr_accessor :from, :to
+ end
+
+
+ let(:lead){Lead.new}
+ before :each do
+ lead.links_clicked = ['2012-12-12', '2012-12-15', '2012-12-16']
+ conversion = Conversion.new
+ conversion.from = 'whatever'
+ conversion.to = 'whatever'
+ lead.conversion = conversion
+ @hash = SchemaTools::Hash.from_schema(lead)
+ end
+ after :each do
+ SchemaTools::Reader.registry_reset
+ end
+
+ it 'should create array with values' do
+ @hash['lead']['links_clicked'].should == lead.links_clicked
+ end
+
+ it 'should create object with values' do
+ @hash['lead']['conversion']['from'].should == lead.conversion.from
+ @hash['lead']['conversion']['to'].should == lead.conversion.to
+ end
+
+ end
end

0 comments on commit 6278fab

Please sign in to comment.