lib/snaky_hash/snake.rb in snaky_hash-1.0.1 vs lib/snaky_hash/snake.rb in snaky_hash-2.0.0

- old
+ new

@@ -1,51 +1,72 @@ -require "hashie/mash" - +# This is a module-class hybrid. +# +# Hashie's standard SymbolizeKeys is similar to the functionality we want. +# ... but not quite. We need to support both String (for oauth2) and Symbol keys (for oauth). +# include Hashie::Extensions::Mash::SymbolizeKeys module SnakyHash - class Snake < Hashie::Mash - # This is similar to the functionality we want. - # include Hashie::Extensions::Mash::SymbolizeKeys - - protected - - # Converts a key to a string, - # but only if it is able to be converted to a symbol. - # - # @api private - # @param [<K>] key the key to attempt convert to a symbol - # @return [String, K] - def convert_key(key) - key.respond_to?(:to_sym) ? underscore_string(key.to_s) : key + class Snake < Module + def initialize(key_type: :string) + super() + @key_type = key_type end - # Unlike its parent Mash, a SnakyHash::Snake will convert other - # Hashie::Hash values to a SnakyHash::Snake when assigning - # instead of respecting the existing subclass - def convert_value(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 + def included(base) + conversions_module = SnakyModulizer.to_mod(@key_type) + base.include(conversions_module) end - # converts a camel_cased string to a underscore string - # subs spaces with underscores, strips whitespace - # Same way ActiveSupport does string.underscore - def underscore_string(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 + module SnakyModulizer + def self.to_mod(key_type) + Module.new do + # Converts a key to a symbol, or a string, depending on key_type, + # but only if it is able to be converted to a symbol, + # and after underscoring it. + # + # @api private + # @param [<K>] key the key to attempt convert to a symbol + # @return [Symbol, K] + + case key_type + when :string then + define_method(:convert_key) { |key| key.respond_to?(:to_sym) ? underscore_string(key.to_s) : key } + when :symbol then + 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 + + # Unlike its parent Mash, a SnakyHash::Snake will convert other + # Hashie::Hash values to a SnakyHash::Snake when assigning + # instead of respecting the existing subclass + 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 camel_cased string to a underscore string + # subs spaces with underscores, strips whitespace + # Same way ActiveSupport does 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 end end end