class Dynflow::Utils::IndifferentHash

Heaviliy inpired by ActiveSupport::HashWithIndifferentAccess, reasons we don't want to use the original implementation:

1. we don't want any core_ext extensions
2. some users are not happy about seeing the ActiveSupport as
our depednency

Public Class Methods

[](*args) click to toggle source
# File lib/dynflow/utils.rb, line 88
def self.[](*args)
  new.merge!(Hash[*args])
end
new(constructor = {}) click to toggle source
Calls superclass method
# File lib/dynflow/utils.rb, line 71
def initialize(constructor = {})
  if constructor.respond_to?(:to_hash)
    super()
    update(constructor)
  else
    super(constructor)
  end
end

Public Instance Methods

[]=(key, value) click to toggle source
# File lib/dynflow/utils.rb, line 95
    def []=(key, value)
      regular_writer(convert_key(key), convert_value(value, for: :assignment))
    end

    alias_method :store, :[]=

    def update(other_hash)
      if other_hash.is_a? IndifferentHash
        super(other_hash)
      else
        other_hash.to_hash.each_pair do |key, value|
          if block_given? && key?(key)
            value = yield(convert_key(key), self[key], value)
          end
          regular_writer(convert_key(key), convert_value(value))
        end
        self
      end
    end

    alias_method :merge!, :update

    def key?(key)
      super(convert_key(key))
    end

    alias_method :include?, :key?
    alias_method :has_key?, :key?
    alias_method :member?, :key?

    def fetch(key, *extras)
      super(convert_key(key), *extras)
    end

    def values_at(*indices)
      indices.collect { |key| self[convert_key(key)] }
    end

    def dup
      self.class.new(self).tap do |new_hash|
        new_hash.default = default
      end
    end

    def merge(hash, &block)
      self.dup.update(hash, &block)
    end

    def reverse_merge(other_hash)
      super(self.class.new_from_hash_copying_default(other_hash))
    end

    def reverse_merge!(other_hash)
      replace(reverse_merge( other_hash ))
    end

    def replace(other_hash)
      super(self.class.new_from_hash_copying_default(other_hash))
    end

    def delete(key)
      super(convert_key(key))
    end

    def stringify_keys!; self end
    def deep_stringify_keys!; self end
    def stringify_keys; dup end
    def deep_stringify_keys; dup end
    def to_options!; self end

    def select(*args, &block)
      dup.tap { |hash| hash.select!(*args, &block) }
    end

    def reject(*args, &block)
      dup.tap { |hash| hash.reject!(*args, &block) }
    end

    # Convert to a regular hash with string keys.
    def to_hash
      _new_hash = Hash.new(default)
      each do |key, value|
        _new_hash[key] = convert_value(value, for: :to_hash)
      end
      _new_hash
    end

    protected
    def convert_key(key)
      key.kind_of?(Symbol) ? key.to_s : key
    end

    def convert_value(value, options = {})
      if value.is_a? Hash
        if options[:for] == :to_hash
          value.to_hash
        else
          Utils.indifferent_hash(value)
        end
      elsif value.is_a?(Array)
        unless options[:for] == :assignment
          value = value.dup
        end
        value.map! { |e| convert_value(e, options) }
      else
        value
      end
    end
  end
end
Also aliased as: regular_writer
convert_key(key) click to toggle source
# File lib/dynflow/utils.rb, line 183
def convert_key(key)
  key.kind_of?(Symbol) ? key.to_s : key
end
convert_value(value, options = {}) click to toggle source
# File lib/dynflow/utils.rb, line 187
def convert_value(value, options = {})
  if value.is_a? Hash
    if options[:for] == :to_hash
      value.to_hash
    else
      Utils.indifferent_hash(value)
    end
  elsif value.is_a?(Array)
    unless options[:for] == :assignment
      value = value.dup
    end
    value.map! { |e| convert_value(e, options) }
  else
    value
  end
end
deep_stringify_keys() click to toggle source
# File lib/dynflow/utils.rb, line 162
def deep_stringify_keys; dup end
deep_stringify_keys!() click to toggle source
# File lib/dynflow/utils.rb, line 160
def deep_stringify_keys!; self end
default(key = nil) click to toggle source
Calls superclass method
# File lib/dynflow/utils.rb, line 80
def default(key = nil)
  if key.is_a?(Symbol) && include?(key = key.to_s)
    self[key]
  else
    super
  end
end
delete(key) click to toggle source
Calls superclass method
# File lib/dynflow/utils.rb, line 155
def delete(key)
  super(convert_key(key))
end
dup() click to toggle source
# File lib/dynflow/utils.rb, line 133
def dup
  self.class.new(self).tap do |new_hash|
    new_hash.default = default
  end
end
fetch(key, *extras) click to toggle source
Calls superclass method
# File lib/dynflow/utils.rb, line 125
def fetch(key, *extras)
  super(convert_key(key), *extras)
end
key?(key) click to toggle source
Calls superclass method
# File lib/dynflow/utils.rb, line 117
def key?(key)
  super(convert_key(key))
end
merge(hash, &block) click to toggle source
# File lib/dynflow/utils.rb, line 139
def merge(hash, &block)
  self.dup.update(hash, &block)
end
regular_update(other_hash)
Alias for: update
regular_writer(key, value)
Alias for: []=
reject(*args, &block) click to toggle source
# File lib/dynflow/utils.rb, line 169
def reject(*args, &block)
  dup.tap { |hash| hash.reject!(*args, &block) }
end
replace(other_hash) click to toggle source
Calls superclass method
# File lib/dynflow/utils.rb, line 151
def replace(other_hash)
  super(self.class.new_from_hash_copying_default(other_hash))
end
reverse_merge(other_hash) click to toggle source
Calls superclass method
# File lib/dynflow/utils.rb, line 143
def reverse_merge(other_hash)
  super(self.class.new_from_hash_copying_default(other_hash))
end
reverse_merge!(other_hash) click to toggle source
# File lib/dynflow/utils.rb, line 147
def reverse_merge!(other_hash)
  replace(reverse_merge( other_hash ))
end
select(*args, &block) click to toggle source
# File lib/dynflow/utils.rb, line 165
def select(*args, &block)
  dup.tap { |hash| hash.select!(*args, &block) }
end
stringify_keys() click to toggle source
# File lib/dynflow/utils.rb, line 161
def stringify_keys; dup end
stringify_keys!() click to toggle source
# File lib/dynflow/utils.rb, line 159
def stringify_keys!; self end
to_hash() click to toggle source

Convert to a regular hash with string keys.

# File lib/dynflow/utils.rb, line 174
  def to_hash
    _new_hash = Hash.new(default)
    each do |key, value|
      _new_hash[key] = convert_value(value, for: :to_hash)
    end
    _new_hash
  end

  protected
  def convert_key(key)
    key.kind_of?(Symbol) ? key.to_s : key
  end

  def convert_value(value, options = {})
    if value.is_a? Hash
      if options[:for] == :to_hash
        value.to_hash
      else
        Utils.indifferent_hash(value)
      end
    elsif value.is_a?(Array)
      unless options[:for] == :assignment
        value = value.dup
      end
      value.map! { |e| convert_value(e, options) }
    else
      value
    end
  end
end
to_options!() click to toggle source
# File lib/dynflow/utils.rb, line 163
def to_options!; self end
update(other_hash) { |convert_key(key), self, value| ... } click to toggle source
Calls superclass method
# File lib/dynflow/utils.rb, line 101
def update(other_hash)
  if other_hash.is_a? IndifferentHash
    super(other_hash)
  else
    other_hash.to_hash.each_pair do |key, value|
      if block_given? && key?(key)
        value = yield(convert_key(key), self[key], value)
      end
      regular_writer(convert_key(key), convert_value(value))
    end
    self
  end
end
Also aliased as: regular_update
values_at(*indices) click to toggle source
# File lib/dynflow/utils.rb, line 129
def values_at(*indices)
  indices.collect { |key| self[convert_key(key)] }
end