Class: Meander::Mutable

Inherits:
Thor::CoreExt::HashWithIndifferentAccess
  • Object
show all
Extended by:
Forwardable
Includes:
Enumerable, CommonMethods
Defined in:
lib/meander/mutable.rb

Overview

This class is a mutable version of Meander::Plain

All keys you alter will be keep up to date if dependend objects updated

Usage

Nesting value updates

a = {}
m = Meander::Mutable.new(a)
a['key'] = 1
m.key       # => 1

Value overloading

a = {}
m = Meander::Mutable.new(a)
m.key = 1
m.key       # => 1
a           # => {}

Deep value overloading

a = {a: {b: {c: 1}}}
m = Meander::Mutable.new(a)
m.a.b.merge!({d: 2})
m.a.b.c     # => 1
m.a.b.d     # => 2
a           # => {a: {b: {c: 1}}}
a[:a][:b][:c] = 3
m.a.b.c     # => 3

Notice

Meander::Mutable support multiple object references

a = {a: 1}
m = Meander::Mutable.new(a)
b = {b: 2}
m.merge!(b)
a[:a] = 3
b[:b] = 4
m.a # => 3  # Value is up to date
m.b # => 4  # This value is also up to date

You can also initialize Meander::Mutable with multiple nested hashes

a = {a: 1}
b = {b: 2}
m = Meander::Mutable.new(a, b)
a[:a] = 3
b[:b] = 4
m.a # => 3  # Value is up to date
m.b # => 4  # This value is also up to date

Class Method Summary collapse

Instance Method Summary collapse

Methods included from CommonMethods

included

Constructor Details

#initialize(required = {}, *args) ⇒ Mutable

Returns a new instance of Mutable.



61
62
63
64
# File 'lib/meander/mutable.rb', line 61

def initialize(required = {}, *args)
  __setobj__(required, *args)
  @own_keys = self.class.own_keys_cover_class.new
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args, &block) ⇒ Object



117
118
119
120
121
122
123
124
125
# File 'lib/meander/mutable.rb', line 117

def method_missing(method_name, *args, &block)
  if @own_keys.respond_to?(method_name) || block_given?
    @own_keys.send method_name, *args, &block
  elsif delegated_key?(method_name)
    self[method_name]
  else
    super
  end
end

Class Method Details

.own_keys_cover_classObject



54
55
56
57
58
59
# File 'lib/meander/mutable.rb', line 54

def self.own_keys_cover_class
  klass = self
  @own_keys_cover_class ||= Class.new(Plain) do
    self.cover_class = klass
  end
end

Instance Method Details

#[](key) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/meander/mutable.rb', line 99

def [](key)
  val = nil
  if @own_keys.key? key
    val = @own_keys[key]
  else
    val = get_delegated_value(key)
    if val.is_a?(Hash)
      val = self.class.new(val)
      self[key] = val
    end
  end
  val
end

#__getobj__Object



66
67
68
# File 'lib/meander/mutable.rb', line 66

def __getobj__
  @delegate
end

#__setobj__(*args) ⇒ Object



70
71
72
73
74
# File 'lib/meander/mutable.rb', line 70

def __setobj__(*args)
  @delegate = []
  @delegate += args
  @delegate
end

#dupObject



85
86
87
# File 'lib/meander/mutable.rb', line 85

def dup
  self.class.new(*__getobj__)
end

#each(*args, &block) ⇒ Object



89
90
91
92
93
# File 'lib/meander/mutable.rb', line 89

def each(*args, &block)
  return enum_for(:each) unless block_given?

  deep_call.each { |i| i.each(*args, &block) }
end

#key?(key) ⇒ Boolean

Returns:

  • (Boolean)


81
82
83
# File 'lib/meander/mutable.rb', line 81

def key?(key)
  @own_keys.key?(key) || delegated_key?(key)
end

#keysObject



95
96
97
# File 'lib/meander/mutable.rb', line 95

def keys
  map { |k, _| convert_key(k) }
end

#kind_of?(klass) ⇒ Boolean Also known as: is_a?

Returns:

  • (Boolean)


127
128
129
# File 'lib/meander/mutable.rb', line 127

def kind_of?(klass)
  (self.class.cover_class == klass) || __getobj__.all?(klass)
end

#merge!(hsh) ⇒ Object



76
77
78
79
# File 'lib/meander/mutable.rb', line 76

def merge!(hsh)
  @delegate ||= []
  @delegate.unshift hsh
end

#respond_to_missing?(method_name, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


113
114
115
# File 'lib/meander/mutable.rb', line 113

def respond_to_missing?(method_name, include_private = false)
  @own_keys.respond_to?(method_name) || delegated_key?(method_name) || super
end