aglushkov/serega

View on GitHub
lib/serega/utils/to_hash.rb

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
# frozen_string_literal: true

class Serega
  module SeregaUtils
    #
    # Utility to transform almost anything to Hash
    #
    class ToHash
      class << self
        #
        # Constructs deep hashes from provided data
        #
        # @param value [Array, Hash, String, Symbol, NilClass, FalseClass] Value to transform
        #
        # @example
        #   Serega::SeregaUtils::ToHash.(nil) # => {}
        #   Serega::SeregaUtils::ToHash.(false) # => {}
        #   Serega::SeregaUtils::ToHash.(:foo) # => {:foo=>{}}
        #   Serega::SeregaUtils::ToHash.("foo") # => {:foo=>{}}
        #   Serega::SeregaUtils::ToHash.(%w[foo bar]) # => {:foo=>{}, :bar=>{}}
        #   Serega::SeregaUtils::ToHash.({ foo: nil, bar: false }) # => {:foo=>{}, :bar=>{}}
        #   Serega::SeregaUtils::ToHash.({ foo: :bar }) # => {:foo=>{:bar=>{}}}
        #   Serega::SeregaUtils::ToHash.({ foo: [:bar] }) # => {:foo=>{:bar=>{}}}
        #
        # @return [Hash] Transformed data
        #
        def call(value)
          case value
          when Array then array_to_hash(value)
          when Hash then hash_to_hash(value)
          when NilClass, FalseClass then nil_to_hash(value)
          when String then string_to_hash(value)
          when Symbol then symbol_to_hash(value)
          else raise SeregaError, "Can't convert #{value.class} class object to hash"
          end
        end

        private

        def array_to_hash(values)
          return FROZEN_EMPTY_HASH if values.empty?

          res = {}
          values.each do |value|
            case value
            when String then res[value.to_sym] = FROZEN_EMPTY_HASH
            when Symbol then res[value] = FROZEN_EMPTY_HASH
            else res.merge!(call(value))
            end
          end
          res
        end

        def hash_to_hash(values)
          return FROZEN_EMPTY_HASH if values.empty?

          res = {}
          values.each do |key, value|
            res[key.to_sym] = call(value)
          end
          res
        end

        def nil_to_hash(_value)
          FROZEN_EMPTY_HASH
        end

        def string_to_hash(value)
          {value.to_sym => FROZEN_EMPTY_HASH}
        end

        def symbol_to_hash(value)
          {value => FROZEN_EMPTY_HASH}
        end
      end
    end
  end
end