Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
Size: Mime:
# frozen_string_literal: true

require 'set'
require 'datasync/exceptions'
require 'datasync/sync_operation'
require 'datasync/sync_runner'

module Datasync
  # Base mapper class
  class Mapper
    attr_accessor :title, :source_key, :source_proc, :target_key, :target_proc,
                  :mapping_proc, :match_fields, :match_situations, :target_key_from_db

    def initialize
      @handler = {}
      @parser = {}
      @formatter = {}
      @limit = {}
      @match_fields = []
      @match_situations = []
      @target_key_from_db = true
    end

    def parser(field, parse_proc)
      @parser[field] = parse_proc
    end

    def formatter(field, format_proc)
      @formatter[field] = format_proc
    end

    def handler(situation, handler)
      @handler[situation] = handler
    end

    def limit(situation, maximum)
      @limit[situation] = maximum
    end

    def limits
      @limit
    end

    def handle(operation, situation, source, target)
      @handler[situation].call(self, operation, situation, source, target) if @handler.key? situation
    end

    def parse(raw_source)
      parsed_fields = @parser.map do |field, parser_proc|
        value = raw_source[field]
        parsed_value = parser_proc.call(value)

        [field, parsed_value]
      end
      raw_source.merge Hash[parsed_fields]
    rescue StandardError => e
      raise ParserError, e.to_s
    end

    def map(...)
      mapping_proc.call(...)
    rescue StandardError => e
      raise MapperError, e.to_s
    end

    def format(mapped_object)
      formatted_fields = @formatter.map do |field, formatter_proc|
        value = mapped_object[field]
        formatted_value = formatter_proc.call(value)

        [field, formatted_value]
      end
      mapped_object.merge Hash[formatted_fields]
    rescue StandardError => e
      raise FormatterError, e.to_s
    end

    def matching_valid?
      return true if @match_situations.empty?
      return false if @match_fields.empty?

      true
    end

    def option(name, *)
      raise OptionError, "Unknown option #{name}"
    end

    def validate! # rubocop:disable Metrics/CyclomaticComplexity
      raise ValidationError, 'Title must be specified' unless @title
      raise ValidationError, 'Source must be specified' unless @source_key && @source_proc
      raise ValidationError, 'Target must be specified' unless @target_key && @target_proc
      raise ValidationError, 'Matching is specified, but no fields' unless matching_valid?
      raise ValidationError, 'Mapping must be specified' unless @mapping_proc
    end

    def sync!
      operation = SyncRunner.new(sync_class.new(self))
      operation.run!
      operation
    end
  end
end