lib/eco/language/models/parser_serializer.rb in eco-helpers-1.5.1 vs lib/eco/language/models/parser_serializer.rb in eco-helpers-1.5.2

- old
+ new

@@ -1,68 +1,92 @@ module Eco module Language module Models - + # Basic class to define a parser/serializing framework + # @attr_reader attr [String, Symbol] the attribute this parser/serializer is linked to. class ParserSerializer - attr_reader :attr # Parser/seralizer. # @param attr [String, Symbol] name of the parsed/serialized. # @param dependencies [Hash] provisioning of _**default dependencies**_ that will be required when calling back to the - # parsing or serializing functions. + # parsing or serializing functions. def initialize(attr, dependencies: {}) - @attr = attr + @attr = attr @dependencies = dependencies + @parser = {} + @serializer = {} end # Defines the _parser_ of the attribute. # @note # 1. the _block_ should expect one or two parameters. # 2. the final dependencies is a merge of _default dependencies_ with `parse` call dependencies. + # @param category [Symbol] a way to classify multiple parsers by category. # @yield [source_data, dependencies] user defined parser that returns the parsed value. # @yieldparam source_data [Any] source data that will be parsed. # @yieldparam dependencies [Hash] hash with the provisioned dependencies. - def def_parser(&block) - @parser = block + def def_parser(category = :default, &block) + @parser[category.to_sym] = block self end # Defines the _serializer_ of the attribute. # @note # 1. the block should expect one or two parameters. # 2. the final dependencies is a merge of _default dependencies_ with `serialize` call dependencies. + # @param category [Symbol] a way to classify multiple serializers by category. # @yield [source_data, dependencies] user defined serialiser that returns the serialised value. # @yieldparam source_data [Any] source data that will be serialised. # @yieldparam dependencies [Hash] hash with the provisioned dependencies. - def def_serializer(&block) - @serializer = block + def def_serializer(category = :default, &block) + @serializer[category.to_sym] = block self end # Calls the `parser` of this attribute by passing `source` and resolved dependencies. # @note # - the method depenencies override keys of the _default dependencies_. # @raise [Exception] when there is **no** `parser` defined. # @param source [Any] source data to be parsed. # @param dependencies [Hash] _additional dependencies_ that should be merged to the _default dependencies_. - def parse(source, dependencies: {}) - raise "There is no parser for this attribue '#{attr}'" if !@parser - @parser.call(source, @dependencies.merge(dependencies), attr) + def parse(source, category = :default, dependencies: {}) + raise "There is no parser of type '#{category}' for this attribue '#{attr}'" unless parser_category?(category) + call_block(source, @dependencies.merge(dependencies), attr, &@parser[category.to_sym]) end # Calls the `serializer` of this attribute by passing `object` and resolved dependencies. # @note # - the method depenencies override keys of the _default dependencies_. # @raise [Exception] when there is **no** `serializer` defined. # @param object [Any] source data to be serialized. # @param dependencies [Hash] _additional dependencies_ that should be merged to the _default dependencies_. - def serialize(object, dependencies: {}) - raise "There is no serializer for this attribue '#{attr}'" if !@serializer - @serializer.call(object, @dependencies.merge(dependencies), attr) + def serialize(object, category = :default, dependencies: {}) + raise "There is no serializer of type '#{category}' for this attribue '#{attr}'" unless serializer_category?(category) + call_block(object, @dependencies.merge(dependencies), attr, &@serializer[category.to_sym]) end - end + # Checks if there's a `parser` defined for `category` + # @return [Boolean] `true` if the parser is defined, and `false` otherwise + def parser_category?(category = :default) + @parser.key?(category.to_sym) + end + # Checks if there's a `serializer` defined for `category` + # @return [Boolean] `true` if the serializer is defined, and `false` otherwise + def serializer_category?(category = :default) + @serializer.key?(category.to_sym) + end + + private + + # The methods may expect less parameters from some type of parsers. + # Here, we ensure they are called with the expected number of parameters. + def call_block(*args, &block) + params = block.parameters.zip(args).map(&:last) + yield(*params) + end + + end end end end