lib/eco/api/common/people/person_parser.rb in eco-helpers-0.6.17 vs lib/eco/api/common/people/person_parser.rb in eco-helpers-0.7.1
- old
+ new
@@ -1,97 +1,168 @@
module Eco
module API
module Common
module People
+
+ # Class to define/group a set of parsers/serializers.
+ #
+ # @attr_reader schema [Ecoportal::API::V1::PersonSchema, nil] schema of person details that this parser will be based upon.
+ # @attr_reader details_attrs [Array<String>] internal names of schema details attributes.
+ # @attr_reader all_attrs [Array<String>] all the internal name attributes, including _core_, _account_ and _details_.
class PersonParser
CORE_ATTRS = ["id", "external_id", "email", "name", "supervisor_id"]
ACCOUNT_ATTRS = ["policy_group_ids", "filter_tags", "default_tag"]
TYPE = [:select, :text, :date, :number, :phone_number, :boolean, :multiple]
+ FORMAT = [:csv, :xml, :json]
attr_reader :schema
attr_reader :details_attrs, :all_attrs
attr_reader :defined_attrs
- def initialize(schema: nil) #), logger: nil)
- #self.schema = schema
+ # @example Example of usage:
+ # person_parser = PersonParser.new(schema: schema)
+ # person_parser.define_attribute("example") do |parser|
+ # parser.def_parser do |str, deps|
+ # i = value.to_i rescue 0
+ # i +=5 if deps.dig(:sum_5)
+ # i
+ # end.def_serializer do |value|
+ # value.to_s
+ # end
+ # end
+ # @param schema [Ecoportal::API::V1::PersonSchema, nil] schema of person details that this parser will be based upon.
+ def initialize(schema: nil)
raise "Constructor needs a PersonSchema. Given: #{schema}" if schema && !schema.is_a?(Ecoportal::API::V1::PersonSchema)
@details_attrs = []
@parsers = {}
if schema
@schema = Ecoportal::API::Internal::PersonSchema.new(JSON.parse(schema.doc.to_json))
@details_attrs = @schema&.fields.map { |fld| fld.alt_id }
end
@all_attrs = CORE_ATTRS + ACCOUNT_ATTRS + @details_attrs
- #init_default_parsers if @schema
end
+ # Lists all defined attributes, types and formats.
+ # @return [Array<String>] the list of defined parsers/serializers.
+ def list_defined
+ @parsers.keys
+ end
+
+ # Scopes `source_attrs` using the _**core** attributes_.
+ # @note use this helper to know which among your attributes are **core** ones.
+ # @param source_attrs [Array<String>]
+ # @return [Array<String>] the scoped **core** attributes, if `source_attrs` is not `nil`. All the _core attributes_, otherwise.
def target_attrs_core(source_attrs = nil)
return CORE_ATTRS if !source_attrs
scoped_attrs(source_attrs, CORE_ATTRS)
end
+ # Scopes `source_attrs` using the schema _**details** attributes_.
+ # @note use this helper to know which among your attributes are schema **details** ones.
+ # @param source_attrs [Array<String>]
+ # @return [Array<String>] the scoped **details** attributes, if `source_attrs` is not `nil`. All the _details attributes_, otherwise.
def target_attrs_details(source_attrs = nil)
return @details_attrs if ! source_attrs
scoped_attrs(source_attrs, @details_attrs)
end
+ # Scopes `source_attrs` using the schema _**account** attributes_.
+ # @note use this helper to know which among your attributes are **account** ones.
+ # @param source_attrs [Array<String>]
+ # @return [Array<String>] the scoped **account** attributes, if `source_attrs` is not `nil`. All the _account attributes_, otherwise.
def target_attrs_account(source_attrs = nil)
return ACCOUNT_ATTRS if !source_attrs
scoped_attrs(source_attrs, ACCOUNT_ATTRS)
end
- def defined
- @parsers.keys
- end
-
- def list
- @parsers.keys
- end
-
+ # Returns a list of all the internal attributes of the model that have a parser defined.
+ # @note it excludes any parser that is not in the model, such as type parsers (i.e. ``:boolean`, ``:multiple`)
+ # @return [Array<String>] list of all attribute defined parsers.
def defined_attrs
+ defined = @parsers.keys
defined - (defined - all_attrs)
end
+ # Returns a list of all the internal attributes of the model that do **not** have a parser defined.
+ # @note it excludes any parser that is **not** in the model, such as type parsers (i.e. :boolean, :multiple)
+ # @return [Array<String>] list of all attributes without a defined parser.
def undefined_attrs
all_attrs - defined_attrs
end
+ # @param attr [String] internal name of an attribute.
+ # @return [Boolean] `true` if the attribute `attr` has parser defined, and `false` otherwise.
def defined?(attr)
- !!@parsers[attr]
+ @parsers.key?(attr)
end
- #def append(attr, dependencies: {}, &bloc)
- # @parsers[attr] = into_a(parsers[attr]).push(define_parser(attr, dependencies, &bloc))
- #end
-
- # merges parser overriding self for exisint parsers
+ # Helper to **merge** a set of parsers of another `PersonParser` into the current object.
+ # @note if there are parsers with same name, it **overrides** the ones of the current object with them.
+ # @param parser [Eco::API::Common::People::PersonParser] a `PersonParser` containing defined parsers.
+ # @return [Eco::API::Common::People::PersonParser] the current object (to ease chainig).
def merge(parser)
return self if !parser
raise "Expected a PersonParser object. Given #{parser}" if !parser.is_a?(PersonParser)
@parsers.merge!(parser.hash)
self
end
- def define_attribute(attr, dependencies: {}, &bloc)
- @parsers[attr] = define_parser(attr, dependencies, &bloc)
+
+ # Helper to define and associate a parser/serializer to a type or attribute.
+ # @raise [Exception] if trying to define a parser/serializer for:
+ # - an unkown attribute (`String`)
+ # - an unrecognized type or format (`Symbol`)
+ # @param attr [String] type (`Symbol`) or attribute (`String`) to define the parser/serializer to.
+ # @param dependencies [Hash] dependencies to be used when calling the parser/serializer.
+ # @yield [parser] the definition of the parser.
+ # @yieldparam parser [Eco::Language::Models::ParserSerializer] parser to define.
+ # @return [Eco::API::Common::People::PersonParser] the current object (to ease chainig).
+ def define_attribute(attr, dependencies: {}, &definition)
+ if !valid?(attr)
+ msg = "The attribute '#{attr_to_str(attr)}' is not part of core, account or target schema, or does not match any type: #{@details_attrs}"
+ raise msg
+ end
+
+ Eco::Language::Models::ParserSerializer.new(attr, dependencies: dependencies).tap do |parser|
+ @parsers[attr] = parser
+ definition.call(parser)
+ end
+
self
end
+ # Call to parser `source` value of attribute or type `attr` into an internal valid value.
+ # @note dependencies introduced on `parse` call will be merged with those defined during the
+ # initialization of the parser `attr`.
+ # @raise [Exception] if there is **no** parser for attribute or type `attr`.
+ # @param attr [String] target attribute or type to **parse**.
+ # @param source [Any] source value to be parsed.
+ # @param deps [Hash] key-value pairs of call dependencies.
+ # @return [Any] a valid internal value.
def parse(attr, source, deps: {})
raise "There is no parser for attribute '#{attr}'" if !self.defined?(attr)
@parsers[attr].parse(source, dependencies: deps)
end
+ # Call to serialise `object` value of attribute or type `attr` into an external valid value.
+ # @note dependencies introduced on `serialise` call will be merged with those defined during the
+ # initialization of the parser/serialiser `attr`.
+ # @raise [Exception] if there is **no** serialiser for attribute or type `attr`.
+ # @param attr [String] target attribute or type to **serialize**.
+ # @param object [Any] object value to be serialized.
+ # @param deps [Hash] key-value pairs of call dependencies.
+ # @return a valid external value.
def serialize(attr, object, deps: {})
raise "There is no parser for attribute '#{attr}'" if !self.defined?(attr)
@parsers[attr].serialize(object, dependencies: deps)
end
protected
+ # @return [Hash] attr-parser pairs with all the defined type and attribute parsers/serializers.
def hash
@parsers
end
private
@@ -100,38 +171,27 @@
direct_attrs = source_attrs & section_attrs
parsed_attrs = @parsers.keys & section_attrs
(source_attrs + parsed_attrs) & (direct_attrs + parsed_attrs)
end
- def define_parser(attr, dependencies = {}, &definition)
- if !valid?(attr)
- str_attr = (attr.is_a?(Symbol) ? ":" : "") + attr.to_s
- msg = "The attribute '#{str_attr}' is not part of core, account or target schema, or does not match any type: #{@details_attrs}"
- raise msg
- end
- parser = Eco::Language::Models::AttributeParser.new(attr, dependencies: dependencies)
- #yield(parser)
- definition.call(parser)
- parser
+ def attr_to_str(attr)
+ attr.is_a?(Symbol)? ":#{attr.to_s}" : "#{attr.to_s}"
end
def valid?(attr)
- (attr.is_a?(Symbol) && valid_type?(attr)) ||
- (attr.is_a?(String) && (!@schema || valid_attr?(attr)))
+ valid_attr?(attr) || valid_type?(attr) || valid_format?(attr)
end
def valid_attr?(attr)
- @all_attrs.include?(attr)
+ attr.is_a?(String) && (!@schema || @all_attrs.include?(attr))
end
def valid_type?(attr)
- TYPE.include?(attr)
+ attr.is_a?(Symbol) && TYPE.include?(attr)
end
- def into_a(value)
- value = [] if value == nil
- value = [].push(value) unless value.is_a?(Array)
- value
+ def valid_format?(attr)
+ attr.is_a?(Symbol) && FORMAT.include?(attr)
end
end
end
end