#!/usr/bin/env ruby # frozen_string_literal: true # encoding=utf-8 class DOH < Hash # Initialize with an optional hash and a block def initialize(initial_hash = {}, &block) super() # Initialize the parent Hash self.merge!(initial_hash) # Merge the initial hash into the current hash self.default_proc = block if block_given? end # Override method_missing to pass undefined methods to the parent Hash def method_missing(method_name, *args, &block) # sc = caller[0].split; pp ['DOH.mm',method_name,sc[-1],sc[-2].split('/')[-1].split(':')[0..1].join(':')] if Hash.instance_methods.include?(method_name) super else raise NoMethodError, "undefined method `#{method_name}` for #{self}:#{self.class}" end end # Ensure respond_to_missing? is correctly implemented def respond_to_missing?(method_name, include_private = false) # sc = caller[0].split; pp ['DOH.rtm?',method_name,sc[-1],sc[-2].split('/')[-1].split(':')[0..1].join(':')] Hash.instance_methods.include?(method_name) || super end end # class DOH < Hash # # Initialize with an optional hash and a block # def initialize(initial_hash = {}, &block) # super() # Initialize the parent Hash # self.merge!(initial_hash) # Merge the initial hash into the current hash # self.default_proc = block if block_given? # end # # Override method_missing to pass undefined methods to the parent Hash # def method_missing(method_name, *args, &block) # # pp ['DOH.mm',method_name] # if self.respond_to?(method_name) # self.send(method_name, *args, &block) # else # super # end # end # # Ensure respond_to_missing? is correctly implemented # # pp ['DOH.rtm?',method_name] # def respond_to_missing?(method_name, include_private = false) # self.respond_to?(method_name) || super # end # end # class LayeredHash # def initialize(table = {}, layers: %i[main]) # @layers = layers.map { |layer| [layer, {}] }.to_h # @current_layer = layers.first # @layers[@current_layer] = table # end # private # def method_missing(method, *args, &block) # method_name = method.to_s # if @layers.respond_to?(method_name) # @layers.send(method_name, *args, &block) # elsif method_name[-1] == '=' # @layers[method_name.chop.to_sym] = args[0] # elsif @layers.respond_to?(method_name) # @layers.send(method_name, *args) # else # @layers[method_name.to_sym] # end # rescue StandardError => err # warn("ERROR ** LayeredHash.method_missing(method: #{method_name}," \ # " *args: #{args.inspect}, &block)") # warn err.inspect # warn(caller[0..4]) # raise err # end # public # # Retrieves the value of a key from the current layer using hash notation # def [](key) # raise "Current layer not set" unless @current_layer # get_from_layer(@current_layer, key) # end # # Sets a key-value pair in the current layer using hash notation # def []=(key, value) # raise "Current layer not set" unless @current_layer # set(@current_layer, key, value) # end # def fetch(key, *args) # key_sym = key.to_sym # if respond_to?("get_#{key}") # send("get_#{key}") # # elsif @table.key?(key_sym) # elsif @layers[@current_layer].key?(key_sym) # # @table[key_sym] # @layers[@current_layer][key_sym] # elsif block_given? # yield key_sym # elsif args.count.positive? # # binding.irb # args.first # else # binding.irb # raise KeyError, "key not found: #{key}" # end.tap{|ret| pp([__LINE__,"Poly.fetch #{key} #{args}",'->',ret]) if $pd } # end # # Retrieves the value of a key from the highest priority layer that has a value # def get(key) # @layers.reverse_each do |_, hash| # return hash[key] if hash.key?(key) # end # nil # end # # Retrieves the value of a key from the specified layer # def get_from_layer(layer, key) # if @layers.key?(layer) # @layers[layer][key] # else # raise ArgumentError, "Layer #{layer} does not exist" # end # end # def merge(*args) # @layers.merge(*args).tap{|ret| pp([__LINE__,"LayeredHash.merge",'->',ret]) if $pd } # end # def respond_to_missing?(method_name, include_private = false) # @layers.key?(method_name.to_sym) || super # end # # Sets a key-value pair in the specified layer # def set(layer, key, value) # if @layers.key?(layer) # @layers[layer][key] = value # else # raise ArgumentError, "Layer #{layer} does not exist" # end # end # # Sets the current layer for use with hash notation ([]) # def set_current_layer(layer) # if @layers.key?(layer) # @current_layer = layer # else # raise ArgumentError, "Layer #{layer} does not exist" # end # end # def to_h # @layers.to_h # end # end return if $PROGRAM_NAME != __FILE__ # layered_hash = LayeredHash.new(layers: %i[low high]) # # Set current layer # layered_hash.set_current_layer(:low) # # Set values in the current layer using hash notation # layered_hash[:key1] = 'low_value' # layered_hash[:key2] = 'low_only_value' # # Switch current layer # layered_hash.set_current_layer(:high) # # Set values in the new current layer using hash notation # layered_hash[:key1] = 'high_value' # # Get value from the specific current layer using hash notation # puts layered_hash[:key1] # Output: 'high_value' # # Get value from the highest priority layer # puts layered_hash.get(:key1) # Output: 'high_value' # puts layered_hash.get(:key2) # Output: 'low_only_value'