Module: SnakyHash::Snake::SnakyModulizer

Defined in:
lib/snaky_hash/snake.rb

Overview

Internal module factory for creating key conversion functionality

Class Method Summary collapse

Class Method Details

.to_mod(key_type) ⇒ Module

Creates a new module with key conversion methods based on the specified key type

Parameters:

  • key_type (Symbol)

    the type to convert keys to (:string or :symbol)

Returns:

  • (Module)

    a new module with conversion methods

Raises:

  • (ArgumentError)

    if key_type is not supported



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/snaky_hash/snake.rb', line 56

def to_mod(key_type)
  Module.new do
    case key_type
    when :string then
      # Converts a key to a string if possible, after underscoring
      #
      # @param key [Object] the key to convert
      # @return [String, Object] the converted key or original if not convertible
      define_method(:convert_key) { |key| key.respond_to?(:to_sym) ? underscore_string(key.to_s) : key }
    when :symbol then
      # Converts a key to a symbol if possible, after underscoring
      #
      # @param key [Object] the key to convert
      # @return [Symbol, Object] the converted key or original if not convertible
      define_method(:convert_key) { |key| key.respond_to?(:to_sym) ? underscore_string(key.to_s).to_sym : key }
    else
      raise ArgumentError, "SnakyHash: Unhandled key_type: #{key_type}"
    end

    # Converts hash values to the appropriate type when assigning
    #
    # @param val [Object] the value to convert
    # @param duping [Boolean] whether the value is being duplicated
    # @return [Object] the converted value
    define_method :convert_value do |val, duping = false| #:nodoc:
      case val
      when self.class
        val.dup
      when ::Hash
        val = val.dup if duping
        self.class.new(val)
      when ::Array
        val.collect { |e| convert_value(e) }
      else
        val
      end
    end

    # Converts a string to underscore case
    #
    # @param str [String, #to_s] the string to convert
    # @return [String] the underscored string
    # @example
    #   underscore_string("CamelCase")  #=> "camel_case"
    #   underscore_string("API::V1")    #=> "api/v1"
    # @note This is the same as ActiveSupport's String#underscore
    define_method :underscore_string do |str|
      str.to_s.strip.
        tr(" ", "_").
        gsub("::", "/").
        gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
        gsub(/([a-z\d])([A-Z])/, '\1_\2').
        tr("-", "_").
        squeeze("_").
        downcase
    end
  end
end