Class: Meander::Mutable

Inherits:
Delegator
  • Object
show all
Extended by:
Forwardable
Includes:
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 only one up to date object reference

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 # => 2  # Attention! Value remains unchanged

Class Method Summary collapse

Instance Method Summary collapse

Methods included from CommonMethods

included

Constructor Details

#initialize(obj = {}) ⇒ Mutable

Returns a new instance of Mutable.



51
52
53
54
55
# File 'lib/meander/mutable.rb', line 51

def initialize(obj = {})
  super
  @delegate_sd_obj = obj
  @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, *args, &block) ⇒ Object



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

def method_missing(method, *args, &block)
  if @own_keys.respond_to?(method) || block_given?
    @own_keys.send method, *args, &block
  elsif delegated_key? method
    define_getter method
    send method, *args, &block
  else
    super
  end
end

Class Method Details

.own_keys_cover_classObject



44
45
46
47
48
49
# File 'lib/meander/mutable.rb', line 44

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



84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/meander/mutable.rb', line 84

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



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

def __getobj__
  @delegate_sd_obj
end

#__setobj__(obj) ⇒ Object



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

def __setobj__(obj)
  @delegate_sd_obj = obj
end

#is_a?(klass) ⇒ Boolean

Returns:

  • (Boolean)


73
74
75
# File 'lib/meander/mutable.rb', line 73

def is_a?(klass)
  klass.ancestors.include?(Hash) || super
end

#key?(key) ⇒ Boolean

Returns:

  • (Boolean)


65
66
67
68
69
70
71
# File 'lib/meander/mutable.rb', line 65

def key?(key)
  @own_keys.key?(key) ||
    begin
      obj = __getobj__
      obj.key?(key.to_s) || obj.key?(key.to_sym)
    end
end

#keysObject



77
78
79
80
81
82
# File 'lib/meander/mutable.rb', line 77

def keys
  origin = __getobj__
  own = @own_keys
  [(origin && origin.keys), (own && own.keys)].flatten
                                              .compact.map(&:to_s).uniq
end

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

Returns:

  • (Boolean)


98
99
100
# File 'lib/meander/mutable.rb', line 98

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