instantiate nested entities if they are provided as hash
also add debug logging to entity constructor
This commit is contained in:
parent
4ded6da139
commit
653b0fe276
2 changed files with 42 additions and 12 deletions
|
|
@ -34,6 +34,7 @@ module DiasporaFederation
|
||||||
# are intended to be immutable data containers, only.
|
# are intended to be immutable data containers, only.
|
||||||
class Entity
|
class Entity
|
||||||
extend PropertiesDSL
|
extend PropertiesDSL
|
||||||
|
include Logging
|
||||||
|
|
||||||
# Initializes the Entity with the given attribute hash and freezes the created
|
# Initializes the Entity with the given attribute hash and freezes the created
|
||||||
# instance it returns.
|
# instance it returns.
|
||||||
|
|
@ -50,15 +51,14 @@ module DiasporaFederation
|
||||||
# @param [Hash] data entity data
|
# @param [Hash] data entity data
|
||||||
# @return [Entity] new instance
|
# @return [Entity] new instance
|
||||||
def initialize(data)
|
def initialize(data)
|
||||||
|
logger.debug "create entity #{self.class} with data: #{data}"
|
||||||
raise ArgumentError, "expected a Hash" unless data.is_a?(Hash)
|
raise ArgumentError, "expected a Hash" unless data.is_a?(Hash)
|
||||||
|
|
||||||
entity_data = self.class.resolv_aliases(data)
|
entity_data = self.class.resolv_aliases(data)
|
||||||
missing_props = self.class.missing_props(entity_data)
|
validate_missing_props(entity_data)
|
||||||
unless missing_props.empty?
|
|
||||||
raise ArgumentError, "missing required properties: #{missing_props.join(', ')}"
|
|
||||||
end
|
|
||||||
|
|
||||||
self.class.default_values.merge(entity_data).each do |name, value|
|
self.class.default_values.merge(entity_data).each do |name, value|
|
||||||
instance_variable_set("@#{name}", nilify(value)) if setable?(name, value)
|
instance_variable_set("@#{name}", instantiate_nested(name, nilify(value))) if setable?(name, value)
|
||||||
end
|
end
|
||||||
|
|
||||||
freeze
|
freeze
|
||||||
|
|
@ -147,6 +147,11 @@ module DiasporaFederation
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def validate_missing_props(entity_data)
|
||||||
|
missing_props = self.class.missing_props(entity_data)
|
||||||
|
raise ArgumentError, "missing required properties: #{missing_props.join(', ')}" unless missing_props.empty?
|
||||||
|
end
|
||||||
|
|
||||||
def setable?(name, val)
|
def setable?(name, val)
|
||||||
type = self.class.class_props[name]
|
type = self.class.class_props[name]
|
||||||
return false if type.nil? # property undefined
|
return false if type.nil? # property undefined
|
||||||
|
|
@ -159,11 +164,12 @@ module DiasporaFederation
|
||||||
end
|
end
|
||||||
|
|
||||||
def setable_nested?(type, val)
|
def setable_nested?(type, val)
|
||||||
type.instance_of?(Class) && type.ancestors.include?(Entity) && val.is_a?(Entity)
|
type.instance_of?(Class) && type.ancestors.include?(Entity) && (val.is_a?(Entity) || val.is_a?(Hash))
|
||||||
end
|
end
|
||||||
|
|
||||||
def setable_multi?(type, val)
|
def setable_multi?(type, val)
|
||||||
type.instance_of?(Array) && val.instance_of?(Array) && val.all? {|v| v.instance_of?(type.first) }
|
type.instance_of?(Array) && val.instance_of?(Array) &&
|
||||||
|
(val.all? {|v| v.instance_of?(type.first) } || val.all? {|v| v.instance_of?(Hash) })
|
||||||
end
|
end
|
||||||
|
|
||||||
def nilify(value)
|
def nilify(value)
|
||||||
|
|
@ -171,6 +177,17 @@ module DiasporaFederation
|
||||||
value
|
value
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def instantiate_nested(name, value)
|
||||||
|
if value.instance_of?(Array)
|
||||||
|
return value unless value.first.instance_of?(Hash)
|
||||||
|
value.map {|hash| self.class.class_props[name].first.new(hash) }
|
||||||
|
elsif value.instance_of?(Hash)
|
||||||
|
self.class.class_props[name].new(value)
|
||||||
|
else
|
||||||
|
value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def validate
|
def validate
|
||||||
validator_name = "#{self.class.name.split('::').last}Validator"
|
validator_name = "#{self.class.name.split('::').last}Validator"
|
||||||
return unless Validators.const_defined? validator_name
|
return unless Validators.const_defined? validator_name
|
||||||
|
|
|
||||||
|
|
@ -250,15 +250,16 @@ XML
|
||||||
multi: [Entities::OtherEntity.new(asdf: "asdf"), Entities::OtherEntity.new(asdf: "asdf")]
|
multi: [Entities::OtherEntity.new(asdf: "asdf"), Entities::OtherEntity.new(asdf: "asdf")]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let(:nested_hash) {
|
||||||
it "gets returned as Hash by #to_h" do
|
{
|
||||||
entity = Entities::TestNestedEntity.new(nested_data)
|
|
||||||
|
|
||||||
nested_hash = {
|
|
||||||
asdf: nested_data[:asdf],
|
asdf: nested_data[:asdf],
|
||||||
test: nested_data[:test].to_h,
|
test: nested_data[:test].to_h,
|
||||||
multi: nested_data[:multi].map(&:to_h)
|
multi: nested_data[:multi].map(&:to_h)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it "gets returned as Hash by #to_h" do
|
||||||
|
entity = Entities::TestNestedEntity.new(nested_data)
|
||||||
|
|
||||||
expect(entity.to_h).to eq(nested_hash)
|
expect(entity.to_h).to eq(nested_hash)
|
||||||
end
|
end
|
||||||
|
|
@ -273,6 +274,18 @@ XML
|
||||||
expect(xml.xpath("test_entity")).to have_exactly(1).items
|
expect(xml.xpath("test_entity")).to have_exactly(1).items
|
||||||
expect(xml.xpath("other_entity")).to have_exactly(2).items
|
expect(xml.xpath("other_entity")).to have_exactly(2).items
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "instantiates nested entities if provided as hash" do
|
||||||
|
entity = Entities::TestNestedEntity.new(nested_hash)
|
||||||
|
|
||||||
|
expect(entity.test).to be_instance_of(Entities::TestEntity)
|
||||||
|
expect(entity.test.test).to eq("test")
|
||||||
|
|
||||||
|
expect(entity.multi).to be_instance_of(Array)
|
||||||
|
expect(entity.multi).to have_exactly(2).items
|
||||||
|
expect(entity.multi.first).to be_instance_of(Entities::OtherEntity)
|
||||||
|
expect(entity.multi.first.asdf).to eq("asdf")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "xml_name" do
|
context "xml_name" do
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue