module SnakyHash::Snake::SnakyModulizer

Internal module factory for creating key conversion functionality

Public Class Methods

to_mod(key_type) click to toggle source

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

@param key_type [Symbol] the type to convert keys to (:string or :symbol) @return [Module] a new module with conversion methods @raise [ArgumentError] if key_type is not supported

    # File lib/snaky_hash/snake.rb
 56 def to_mod(key_type)
 57   Module.new do
 58     case key_type
 59     when :string then
 60       # Converts a key to a string if it is symbolizable, after underscoring
 61       #
 62       # @note checks for to_sym instead of to_s, because nearly everything responds_to?(:to_s)
 63       #       so respond_to?(:to_s) isn't very useful as a test, and would result in symbolizing integers
 64       #       amd it also provides parity between the :symbol behavior, and the :string behavior,
 65       #       regarding which keys get converted for a given version of Ruby.
 66       #
 67       # @param key [Object] the key to convert
 68       # @return [String, Object] the converted key or original if not convertible
 69       define_method(:convert_key) { |key| key.respond_to?(:to_sym) ? underscore_string(key.to_s) : key }
 70     when :symbol then
 71       # Converts a key to a symbol if possible, after underscoring
 72       #
 73       # @param key [Object] the key to convert
 74       # @return [Symbol, Object] the converted key or original if not convertible
 75       define_method(:convert_key) { |key| key.respond_to?(:to_sym) ? underscore_string(key.to_s).to_sym : key }
 76     else
 77       raise ArgumentError, "SnakyHash: Unhandled key_type: #{key_type}"
 78     end
 79 
 80     # Converts hash values to the appropriate type when assigning
 81     #
 82     # @param val [Object] the value to convert
 83     # @param duping [Boolean] whether the value is being duplicated
 84     # @return [Object] the converted value
 85     define_method :convert_value do |val, duping = false| #:nodoc:
 86       case val
 87       when self.class
 88         val.dup
 89       when ::Hash
 90         val = val.dup if duping
 91         self.class.new(val)
 92       when ::Array
 93         val.collect { |e| convert_value(e) }
 94       else
 95         val
 96       end
 97     end
 98 
 99     # Converts a string to underscore case
100     #
101     # @param str [String, #to_s] the string to convert
102     # @return [String] the underscored string
103     # @example
104     #   underscore_string("CamelCase")  #=> "camel_case"
105     #   underscore_string("API::V1")    #=> "api/v1"
106     # @note This is the same as ActiveSupport's String#underscore
107     define_method :underscore_string do |str|
108       str.to_s.strip.
109         tr(" ", "_").
110         gsub("::", "/").
111         gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
112         gsub(/([a-z\d])([A-Z])/, '\1_\2').
113         tr("-", "_").
114         squeeze("_").
115         downcase
116     end
117   end
118 end