class Eco::API::Common::People::PersonParser
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_model_attrs
[Array<String>] all the internal name attributes, including core, account and details.
Constants
- ACCOUNT_ATTRS
- CORE_ATTRS
- FORMAT
- TYPE
Attributes
Public Class Methods
@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.
# File lib/eco/api/common/people/person_parser.rb, line 37 def initialize(schema: nil) raise "Constructor needs a PersonSchema. Given: #{schema}" if schema && !schema.is_a?(Ecoportal::API::V1::PersonSchema) @details_attrs = [] @parsers = {} @patch_version = 0 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_model_attrs = CORE_ATTRS + ACCOUNT_ATTRS + @details_attrs self.class.autoload_children(self) end
Public Instance Methods
Returns a list of all the internal attributes of the model that have a parser defined & that should be active. @param source_data [Hash, Array<String>] the data that we scope for parsing @param phase [Symbol] the phase when the attr parser is expected to be called. Can be [:internal, :final, :person] @param process [Symbol] either `:parse` or `:serialize`, depending if we want to parse or serialize the `attr`. @return [Array<String>] list of all attribute defined parsers that should be active for the given `source_data`.
# File lib/eco/api/common/people/person_parser.rb, line 137 def active_attrs(source_data, phase = :any, process: :parse) defined_model_attrs.select do |attr| if process == :serialize @parsers[attr].serializer_active?(phase) else @parsers[attr].parser_active?(source_data, phase) end end end
All the internal name attributes, including core, account and details.
# File lib/eco/api/common/people/person_parser.rb, line 68 def all_attrs(include_defined_parsers: false) return all_model_attrs | defined_model_attrs if include_defined_parsers all_model_attrs end
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).
# File lib/eco/api/common/people/person_parser.rb, line 184 def define_attribute(attr, dependencies: {}, &definition) unless 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::API::Common::People::PersonAttributeParser.new(attr, dependencies: dependencies).tap do |parser| @parsers[attr] = parser definition.call(parser) end patched! self end
@param attr [String] internal name of an attribute. @return [Boolean] `true` if the attribute `attr` has parser defined, and `false` otherwise.
# File lib/eco/api/common/people/person_parser.rb, line 156 def defined?(attr) @parsers.key?(attr) end
Returns a list of all the internal attributes that have a parser defined. @note These attributes do not necessarily belong to the model. They could be virtual attributes @return [Array<String>] list of all attribute defined parsers.
# File lib/eco/api/common/people/person_parser.rb, line 109 def defined_attrs defined_list - symbol_keys end
Lists all defined attributes, types and formats. @return [Array<String>] the list of defined parsers/serializers.
# File lib/eco/api/common/people/person_parser.rb, line 102 def defined_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`) - the list is sorted according `CORE_ATTRS` + `ACCOUNT_ATTRS` + schema attrs
@return [Array<String>] list of all attribute defined parsers in the model.
# File lib/eco/api/common/people/person_parser.rb, line 118 def defined_model_attrs defined = @parsers.keys defined = (all_model_attrs | defined) & defined defined - symbol_keys end
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).
# File lib/eco/api/common/people/person_parser.rb, line 167 def merge(parser) return self if !parser raise "Expected a PersonParser object. Given #{parser}" if !parser.is_a?(PersonParser) to_h.merge!(parser.to_h) patched! self end
# File lib/eco/api/common/people/person_parser.rb, line 56 def new(schema: nil) self.class.new(schema: schema || self.schema).merge(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 phase [Symbol] the phase when the attr parser is expected to be called.
Must be [:internal, :final]
@param deps [Hash] key-value pairs of call dependencies. @return [Any] a valid internal value.
# File lib/eco/api/common/people/person_parser.rb, line 210 def parse(attr, source, phase = :internal, deps: {}) raise "There is no parser for attribute '#{attr}'" if !self.defined?(attr) @parsers[attr].parse(source, phase, dependencies: deps) end
# File lib/eco/api/common/people/person_parser.rb, line 52 def patched! @patch_version += 1 end
@return [Array<Eco::API::Common::Loaders::Parser::RequiredAttrs>]
# File lib/eco/api/common/people/person_parser.rb, line 63 def required_attrs @parsers.values_at(*all_attrs(include_defined_parsers: true)).compact.map(&:required_attrs).compact 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 phase [Symbol] the phase when the attr serializer is expected to be called.
Must be [:internal, :final, :person]
@param deps [Hash] key-value pairs of call dependencies. @return a valid external value.
# File lib/eco/api/common/people/person_parser.rb, line 225 def serialize(attr, object, phase = :person, deps: {}) raise "There is no parser for attribute '#{attr}'" if !self.defined?(attr) @parsers[attr].serialize(object, phase, dependencies: deps) end
Symbol keys are type or import parsers (that do not belong to the model) @note this was introduced to boost virtual fields to treat in different phases of the parsing process @return [Array<Symbol>] all the parsers defined as Symbol
# File lib/eco/api/common/people/person_parser.rb, line 127 def symbol_keys @parsers.keys.select {|k| k.is_a?(Symbol)} 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.
# File lib/eco/api/common/people/person_parser.rb, line 95 def target_attrs_account(source_attrs = nil) return ACCOUNT_ATTRS if !source_attrs scoped_attrs(source_attrs, ACCOUNT_ATTRS) 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.
# File lib/eco/api/common/people/person_parser.rb, line 77 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.
# File lib/eco/api/common/people/person_parser.rb, line 86 def target_attrs_details(source_attrs = nil) return @details_attrs if !source_attrs scoped_attrs(source_attrs, @details_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.
# File lib/eco/api/common/people/person_parser.rb, line 150 def undefined_model_attrs all_model_attrs - defined_model_attrs end
Protected Instance Methods
@return [Hash] attr-parser pairs with all the defined type and attribute parsers/serializers.
# File lib/eco/api/common/people/person_parser.rb, line 234 def to_h self.class.autoload_children(self) @parsers end
Private Instance Methods
# File lib/eco/api/common/people/person_parser.rb, line 249 def attr_to_str(attr) attr.is_a?(Symbol)? ":#{attr.to_s}" : "#{attr.to_s}" end
Some attribute parsers are inactive, and therefore out of scope @param source_attrs [Array<String>] the attrs we want to filter from to only those in scope. @param section_attrs [Array<String>] the attrs of reference to scope `source_attrs`. @return [Array<String>] the `source_attrs` in `section_attrs` + the `section_attrs` with active parser
# File lib/eco/api/common/people/person_parser.rb, line 245 def scoped_attrs(source_attrs, section_attrs) (source_attrs | active_attrs(source_attrs)) & section_attrs end
# File lib/eco/api/common/people/person_parser.rb, line 253 def valid?(attr) valid_attr?(attr) || valid_type?(attr) || valid_format?(attr) end
# File lib/eco/api/common/people/person_parser.rb, line 257 def valid_attr?(attr) attr.is_a?(String) && (!@schema || @all_model_attrs.include?(attr)) end
# File lib/eco/api/common/people/person_parser.rb, line 265 def valid_format?(attr) attr.is_a?(Symbol) && FORMAT.include?(attr) end
# File lib/eco/api/common/people/person_parser.rb, line 261 def valid_type?(attr) attr.is_a?(Symbol) && TYPE.include?(attr) end