Class: NRSER::Stash

Inherits:
Hash show all
Defined in:
lib/nrser/labs/stash.rb

Overview

Abstract generalization of ActiveSupport::HashWithIndifferentAccess. Extends Hash and provides simple hooks for handling keys and values on write.

The Stuff You Care About collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Hash

#bury, #bury!, #extract_values_at!, #str_keys, #str_keys!, #sym_keys, #sym_keys!, #to_options, #to_options!, #to_pair, #transform_values_with_keys, #transform_values_with_keys!

Methods included from Ext::Tree

#each_branch, #leaves, #map_branches, #map_leaves, #map_tree

Constructor Details

#initialize(constructor = {}) ⇒ Stash

Construction



27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/nrser/labs/stash.rb', line 27

def initialize(constructor = {})
  if constructor.respond_to?(:to_hash)
    super()
    update(constructor)

    hash = constructor.to_hash
    self.default = hash.default if hash.default
    self.default_proc = hash.default_proc if hash.default_proc
  else
    super(constructor)
  end
end

Class Method Details

.[](*args) ⇒ Object



150
151
152
# File 'lib/nrser/labs/stash.rb', line 150

def self.[] *args
  new.merge! ::Hash[*args]
end

Instance Method Details

#[](key) ⇒ Object

Same as Hash#[] where the key passed as argument can be either a string or a symbol:

counters = ActiveSupport::HashWithIndifferentAccess.new
counters[:foo] = 1

counters['foo'] # => 1
counters[:foo]  # => 1
counters[:zoo]  # => nil


226
227
228
# File 'lib/nrser/labs/stash.rb', line 226

def [] key
  _raw_get convert_key( key )
end

#[]=(key, value) ⇒ Object Also known as: store



124
125
126
# File 'lib/nrser/labs/stash.rb', line 124

def []= key, value
  put key, value
end

#_raw_getObject



215
# File 'lib/nrser/labs/stash.rb', line 215

alias_method :_raw_get, :[]

#compactObject



357
358
359
# File 'lib/nrser/labs/stash.rb', line 357

def compact
  dup.tap(&:compact!)
end

#convert_key(key) ⇒ *

Convert an external key to the internal representation.

Parameters:

  • key (*)

    The externally provided key.

Returns:

  • (*)

    The key to use internally.



109
110
111
# File 'lib/nrser/labs/stash.rb', line 109

def convert_key key
  key
end

#convert_value(value, options = {}) ⇒ Object



114
115
116
# File 'lib/nrser/labs/stash.rb', line 114

def convert_value value, options = {}
  value
end

#default(*args) ⇒ Object

Same as Hash#default where the key passed as argument can be either a string or a symbol:

hash = ActiveSupport::HashWithIndifferentAccess.new(1)
hash.default                   # => 1

hash = ActiveSupport::HashWithIndifferentAccess.new { |hash, key| key }
hash.default                   # => nil
hash.default('foo')            # => 'foo'
hash.default(:foo)             # => 'foo'


269
270
271
# File 'lib/nrser/labs/stash.rb', line 269

def default(*args)
  super(*args.map { |arg| convert_key(arg) })
end

#delete(key) ⇒ Object

Removes the specified key from the hash.



328
329
330
# File 'lib/nrser/labs/stash.rb', line 328

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

#dig(*args) ⇒ Object

Same as Hash#dig where the key passed as argument can be either a string or a symbol:

counters = ActiveSupport::HashWithIndifferentAccess.new
counters[:foo] = { bar: 1 }

counters.dig('foo', 'bar')     # => 1
counters.dig(:foo, :bar)       # => 1
counters.dig(:zoo)             # => nil


253
254
255
256
# File 'lib/nrser/labs/stash.rb', line 253

def dig *args
  args[0] = convert_key( args[0] ) if args.size > 0
  super *args
end

#dupObject

Returns a shallow copy of the hash.

hash = ActiveSupport::HashWithIndifferentAccess.new({ a: { b: 'b' } })
dup  = hash.dup
dup[:a][:c] = 'c'

hash[:a][:c] # => "c"
dup[:a][:c]  # => "c"


291
292
293
294
295
# File 'lib/nrser/labs/stash.rb', line 291

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

#extractable_options?Boolean

Returns true so that Array#extract_options! finds members of this class.

Returns:

  • (Boolean)


145
146
147
# File 'lib/nrser/labs/stash.rb', line 145

def extractable_options?
  true
end

#fetch(key, *extras) ⇒ Object

Same as Hash#fetch where the key passed as argument can be either a string or a symbol:

counters = ActiveSupport::HashWithIndifferentAccess.new
counters[:foo] = 1

counters.fetch('foo')          # => 1
counters.fetch(:bar, 0)        # => 0
counters.fetch(:bar) { |key| 0 } # => 0
counters.fetch(:zoo)           # => KeyError: key not found: "zoo"


240
241
242
# File 'lib/nrser/labs/stash.rb', line 240

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

#key?(key) ⇒ Boolean Also known as: include?, has_key?, member?

Checks the hash for a key matching the argument passed in:

hash = ActiveSupport::HashWithIndifferentAccess.new
hash['key'] = 'value'
hash.key?(:key)  # => true
hash.key?('key') # => true

Returns:

  • (Boolean)


206
207
208
# File 'lib/nrser/labs/stash.rb', line 206

def key? key
  _raw_key? convert_key( key )
end

#merge(hash, &block) ⇒ Object

This method has the same semantics of update, except it does not modify the receiver but rather returns a new hash with indifferent access with the result of the merge.



300
301
302
# File 'lib/nrser/labs/stash.rb', line 300

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

#put(key, value) ⇒ Object



119
120
121
# File 'lib/nrser/labs/stash.rb', line 119

def put key, value
  _convert_and_put key, value
end

#reject(*args, &block) ⇒ Object



347
348
349
350
# File 'lib/nrser/labs/stash.rb', line 347

def reject(*args, &block)
  return to_enum(:reject) unless block_given?
  dup.tap { |hash| hash.reject!(*args, &block) }
end

#replace(other_hash) ⇒ Object

Replaces the contents of this hash with other_hash.

h = { "a" => 100, "b" => 200 }
h.replace({ "c" => 300, "d" => 400 }) # => {"c"=>300, "d"=>400}


323
324
325
# File 'lib/nrser/labs/stash.rb', line 323

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

#reverse_merge(other_hash) ⇒ Object

Like merge but the other way around: Merges the receiver into the argument and returns a new hash with indifferent access as result:

hash = ActiveSupport::HashWithIndifferentAccess.new
hash['a'] = nil
hash.reverse_merge(a: 0, b: 1) # => {"a"=>nil, "b"=>1}


310
311
312
# File 'lib/nrser/labs/stash.rb', line 310

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

#reverse_merge!(other_hash) ⇒ Object

Same semantics as reverse_merge but modifies the receiver in-place.



315
316
317
# File 'lib/nrser/labs/stash.rb', line 315

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

#select(*args, &block) ⇒ Object

def stringify_keys!; self end def deep_stringify_keys!; self end def stringify_keys; dup end def deep_stringify_keys; dup end undef :symbolize_keys! undef :deep_symbolize_keys! def symbolize_keys; to_hash.symbolize_keys! end def deep_symbolize_keys; to_hash.deep_symbolize_keys! end def to_options!; self end



342
343
344
345
# File 'lib/nrser/labs/stash.rb', line 342

def select(*args, &block)
  return to_enum(:select) unless block_given?
  dup.tap { |hash| hash.select!(*args, &block) }
end

#set_defaults(target) ⇒ Object



134
135
136
137
138
139
140
# File 'lib/nrser/labs/stash.rb', line 134

def set_defaults(target)
  if default_proc
    target.default_proc = default_proc.dup
  else
    target.default = default
  end
end

#to_hashObject

Convert to a regular hash with string keys.



362
363
364
365
366
367
368
369
370
# File 'lib/nrser/labs/stash.rb', line 362

def to_hash
  _new_hash = ::Hash.new
  set_defaults(_new_hash)

  each do |key, value|
    _new_hash[key] = convert_value(value, for: :to_hash)
  end
  _new_hash
end

#transform_values(*args, &block) ⇒ Object



352
353
354
355
# File 'lib/nrser/labs/stash.rb', line 352

def transform_values(*args, &block)
  return to_enum(:transform_values) unless block_given?
  dup.tap { |hash| hash.transform_values!(*args, &block) }
end

#update(other_hash, &block) ⇒ self Also known as: merge!

Updates the receiver in-place, merging in the hash passed as argument:

hash_1 = ActiveSupport::HashWithIndifferentAccess.new
hash_1[:key] = 'value'

hash_2 = ActiveSupport::HashWithIndifferentAccess.new
hash_2[:key] = 'New Value!'

hash_1.update(hash_2) # => {"key"=>"New Value!"}

The argument can be either an ActiveSupport::HashWithIndifferentAccess or a regular Hash. In either case the merge respects the semantics of indifferent access.

If the argument is a regular hash with keys :key and “key” only one of the values end up in the receiver, but which one is unspecified.

When given a block, the value for duplicated keys will be determined by the result of invoking the block with the duplicated key, the value in the receiver, and the value in other_hash. The rules for duplicated keys follow the semantics of indifferent access:

hash_1[:key] = 10
hash_2['key'] = 12
hash_1.update(hash_2) { |key, old, new| old + new } # => {"key"=>22}

Parameters:

  • block (Proc<(KEY, CURRENT, UPDATE) => VALUE>)

    Optional block to handle key conflicts.

Returns:

  • (self)


186
187
188
189
190
191
192
193
194
195
# File 'lib/nrser/labs/stash.rb', line 186

def update other_hash, &block
  other_hash.to_hash.each_pair do |key, value|
    key = convert_key key
    if block && _raw_key?( key )
      value = yield key, _raw_get( key ), value
    end
    put key, value
  end
  self
end

#values_at(*indices) ⇒ Object

Returns an array of the values at the specified indices:

hash = ActiveSupport::HashWithIndifferentAccess.new
hash[:a] = 'x'
hash[:b] = 'y'
hash.values_at('a', 'b') # => ["x", "y"]


279
280
281
# File 'lib/nrser/labs/stash.rb', line 279

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