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.
|
||||
class Entity
|
||||
extend PropertiesDSL
|
||||
include Logging
|
||||
|
||||
# Initializes the Entity with the given attribute hash and freezes the created
|
||||
# instance it returns.
|
||||
|
|
@ -50,15 +51,14 @@ module DiasporaFederation
|
|||
# @param [Hash] data entity data
|
||||
# @return [Entity] new instance
|
||||
def initialize(data)
|
||||
logger.debug "create entity #{self.class} with data: #{data}"
|
||||
raise ArgumentError, "expected a Hash" unless data.is_a?(Hash)
|
||||
|
||||
entity_data = self.class.resolv_aliases(data)
|
||||
missing_props = self.class.missing_props(entity_data)
|
||||
unless missing_props.empty?
|
||||
raise ArgumentError, "missing required properties: #{missing_props.join(', ')}"
|
||||
end
|
||||
validate_missing_props(entity_data)
|
||||
|
||||
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
|
||||
|
||||
freeze
|
||||
|
|
@ -147,6 +147,11 @@ module DiasporaFederation
|
|||
|
||||
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)
|
||||
type = self.class.class_props[name]
|
||||
return false if type.nil? # property undefined
|
||||
|
|
@ -159,11 +164,12 @@ module DiasporaFederation
|
|||
end
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
def nilify(value)
|
||||
|
|
@ -171,6 +177,17 @@ module DiasporaFederation
|
|||
value
|
||||
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
|
||||
validator_name = "#{self.class.name.split('::').last}Validator"
|
||||
return unless Validators.const_defined? validator_name
|
||||
|
|
|
|||
|
|
@ -250,15 +250,16 @@ XML
|
|||
multi: [Entities::OtherEntity.new(asdf: "asdf"), Entities::OtherEntity.new(asdf: "asdf")]
|
||||
}
|
||||
}
|
||||
|
||||
it "gets returned as Hash by #to_h" do
|
||||
entity = Entities::TestNestedEntity.new(nested_data)
|
||||
|
||||
nested_hash = {
|
||||
let(:nested_hash) {
|
||||
{
|
||||
asdf: nested_data[:asdf],
|
||||
test: nested_data[:test].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)
|
||||
end
|
||||
|
|
@ -273,6 +274,18 @@ XML
|
|||
expect(xml.xpath("test_entity")).to have_exactly(1).items
|
||||
expect(xml.xpath("other_entity")).to have_exactly(2).items
|
||||
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
|
||||
|
||||
context "xml_name" do
|
||||
|
|
|
|||
Loading…
Reference in a new issue