• Jump To … +
    mash.rb stringy_hash.rb version.rb
  • mash.rb

  • ¶
    module Mashed
      class Mash < BasicObject
        def singleton_method_added(symbol)
          @singleton_methods ||= []
          @singleton_methods << symbol
        end
        def singleton_method_removed(symbol)
          @singleton_methods ||= []
          @singleton_methods.delete symbol
        end
        def singleton_method_undefined(symbol)
          singleton_method_removed(symbol)
        end
    
        unless defined?(object_id)
          def object_id
            __id__
          end
        end
    
        def to_hash
          unwrap @hash
        end
        alias to_h to_hash
    
        def to_json(*args)
          to_hash.to_json(*args)
        end
    
        def puts(*args)
          ::Kernel.puts(*args)
        end
    
        klass = self
        define_method(:class) { klass }
        define_method(:methods) { klass.instance_methods + @singleton_methods + keys }
    
        def self.name
          "Mashed::Mash"
        end
    
        def initialize(hash)
          @singleton_methods ||= []
          hash = if hash.respond_to?(:to_h)
            hash.to_h
          else
            hash.to_hash
          end
          @hash = hash.stringify
        end
    
        def is_a?(other)
          other == self.class
        end
        alias kind_of? is_a?
    
        def delete(key)
          wrap_up @hash.delete(key)
        end
    
        def method_missing(symbol, *args, &blk)
          string = symbol.to_s
          if blk
            super
          elsif args.length == 0
            if @hash.key?(string)
              self[string]
            elsif string =~ /\?$/
              !!self[string[0..-2]]
            else
              nil
            end
          elsif args.length == 1 && string =~ /=$/
            self[string[0..-2]] = args.first
          else
            super
          end
        end
    
        def respond_to?(symbol)
          methods.map(&:to_s).include?(symbol.to_s)
        end
    
        def inspect
          "#<Mashed::Mash @hash=>#{@hash.inspect}>"
        end
        alias to_s inspect
    
        def pretty_inspect
          inspect
        end
    
        def pretty_print
          inspect
        end
    
        private
    
        def [](key)
          key = key.to_s
          wrap_up @hash[key]
        end
    
        def []=(key, value)
          key = key.to_s
          @hash[key] = value
        end
    
        def keys
          @hash.keys
        end
    
        def wrap_up(thing)
          if thing.respond_to?(:to_ary)
            thing.map { |t| wrap(t) }
          else
            wrap(thing)
          end
        end
    
        def wrap(thing)
          if thing.respond_to?(:to_hash)
            self.class.new thing
          else
            thing
          end
        end
    
        def unwrap(thing)
          if thing.respond_to?(:to_hash)
            thing.to_hash.each_with_object({}) do |(key, value), hash|
              hash[key] = unwrap(value)
            end
          elsif thing.respond_to?(:to_ary)
            thing.map { |t| unwrap(t) }
          else
            thing
          end
        end
      end
    end