Module: Glimmer::DataBinding::ObservableHash
- Includes:
- Observable
- Defined in:
- lib/glimmer/data_binding/observable_hash.rb
Defined Under Namespace
Classes: Notifier
Constant Summary collapse
- OBSERVED_STORE_METHOD =
lambda do |key, value| if key_observer_list(key).empty? if all_key_observer_list.empty? self.send('__original__store', key, value) else old_value = self[key] unregister_dependent_observers(nil, old_value) # remove dependent observers previously installed in ensure_array_object_observer and ensure_hash_object_observer self.send('__original__store', key, value) notify_observers(key) ensure_array_object_observer(nil, value, old_value) ensure_hash_object_observer(nil, value, old_value) end else old_value = self[key] unregister_dependent_observers(key, old_value) # remove dependent observers previously installed in ensure_array_object_observer and ensure_hash_object_observer self.send('__original__store', key, value) notify_observers(key) ensure_array_object_observer(key, value, old_value) ensure_hash_object_observer(key, value, old_value) end end
Instance Method Summary collapse
- #add_key_writer_observer(key = nil) ⇒ Object
- #add_observer(observer, key = nil) ⇒ Object
- #all_key_observer_list ⇒ Object
- #array_object_observer_for(key) ⇒ Object
- #ensure_array_object_observer(key, object, old_object = nil) ⇒ Object
- #ensure_hash_object_observer(key, object, old_object = nil) ⇒ Object
- #has_observer?(observer, key = nil) ⇒ Boolean
- #has_observer_for_any_key?(observer) ⇒ Boolean
- #hash_object_observer_for(key) ⇒ Object
- #key_observer_hash ⇒ Object
- #key_observer_list(key) ⇒ Object
- #notify_observers(key) ⇒ Object
- #remove_all_observers ⇒ Object
- #remove_observer(observer, key = nil) ⇒ Object
- #remove_observers(key) ⇒ Object
- #store_method ⇒ Object
- #unregister_dependent_observers(key, old_value) ⇒ Object (also: #deregister_dependent_observers)
Methods included from Observable
Instance Method Details
#add_key_writer_observer(key = nil) ⇒ Object
121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/glimmer/data_binding/observable_hash.rb', line 121 def add_key_writer_observer(key = nil) ensure_array_object_observer(key, self[key]) ensure_hash_object_observer(key, self[key]) begin method('__original__store') rescue define_singleton_method('__original__store', store_method) define_singleton_method('[]=', &OBSERVED_STORE_METHOD) end rescue => e #ignore writing if no key writer exists Glimmer::Config.logger.debug {"No need to observe store method: '[]='\n#{e.}\n#{e.backtrace.join("\n")}"} end |
#add_observer(observer, key = nil) ⇒ Object
65 66 67 68 69 70 |
# File 'lib/glimmer/data_binding/observable_hash.rb', line 65 def add_observer(observer, key = nil) return observer if has_observer?(observer, key) key_observer_list(key) << observer add_key_writer_observer(key) observer end |
#all_key_observer_list ⇒ Object
112 113 114 |
# File 'lib/glimmer/data_binding/observable_hash.rb', line 112 def all_key_observer_list key_observer_list(nil) end |
#array_object_observer_for(key) ⇒ Object
157 158 159 160 161 |
# File 'lib/glimmer/data_binding/observable_hash.rb', line 157 def array_object_observer_for(key) @array_object_observers ||= Concurrent::Hash.new @array_object_observers[key] = ObservableModel::Notifier.new(self, key) unless @array_object_observers.has_key?(key) @array_object_observers[key] end |
#ensure_array_object_observer(key, object, old_object = nil) ⇒ Object
146 147 148 149 150 151 152 153 154 155 |
# File 'lib/glimmer/data_binding/observable_hash.rb', line 146 def ensure_array_object_observer(key, object, old_object = nil) return unless object&.is_a?(Array) array_object_observer = array_object_observer_for(key) array_observer_registration = array_object_observer.observe(object) key_observer_list(key).each do |observer| my_registration = observer.registration_for(self, key) # TODO eliminate repetition observer.add_dependent(my_registration => array_observer_registration) end array_object_observer_for(key).unregister(old_object) if old_object.is_a?(ObservableArray) end |
#ensure_hash_object_observer(key, object, old_object = nil) ⇒ Object
163 164 165 166 167 168 169 170 171 172 |
# File 'lib/glimmer/data_binding/observable_hash.rb', line 163 def ensure_hash_object_observer(key, object, old_object = nil) return unless object&.is_a?(Hash) hash_object_observer = hash_object_observer_for(key) hash_observer_registration = hash_object_observer.observe(object) key_observer_list(key).each do |observer| my_registration = observer.registration_for(self, key) # TODO eliminate repetition observer.add_dependent(my_registration => hash_observer_registration) end hash_object_observer_for(key).unregister(old_object) if old_object.is_a?(ObservableHash) end |
#has_observer?(observer, key = nil) ⇒ Boolean
95 96 97 |
# File 'lib/glimmer/data_binding/observable_hash.rb', line 95 def has_observer?(observer, key = nil) key_observer_list(key).include?(observer) end |
#has_observer_for_any_key?(observer) ⇒ Boolean
99 100 101 |
# File 'lib/glimmer/data_binding/observable_hash.rb', line 99 def has_observer_for_any_key?(observer) key_observer_hash.values.map(&:to_a).reduce(:+).include?(observer) end |
#hash_object_observer_for(key) ⇒ Object
174 175 176 177 178 |
# File 'lib/glimmer/data_binding/observable_hash.rb', line 174 def hash_object_observer_for(key) @hash_object_observers ||= Concurrent::Hash.new @hash_object_observers[key] = ObservableModel::Notifier.new(self, key) unless @hash_object_observers.has_key?(key) @hash_object_observers[key] end |
#key_observer_hash ⇒ Object
103 104 105 |
# File 'lib/glimmer/data_binding/observable_hash.rb', line 103 def key_observer_hash @key_observers ||= Hash.new end |
#key_observer_list(key) ⇒ Object
107 108 109 110 |
# File 'lib/glimmer/data_binding/observable_hash.rb', line 107 def key_observer_list(key) key_observer_hash[key] = Concurrent::Set.new unless key_observer_hash[key] key_observer_hash[key] end |
#notify_observers(key) ⇒ Object
116 117 118 119 |
# File 'lib/glimmer/data_binding/observable_hash.rb', line 116 def notify_observers(key) all_key_observer_list.to_a.each { |observer| observer.call(self[key], key) } (key_observer_list(key).to_a - all_key_observer_list.to_a).each { |observer| observer.call(self[key]) } end |
#remove_all_observers ⇒ Object
86 87 88 89 90 91 92 93 |
# File 'lib/glimmer/data_binding/observable_hash.rb', line 86 def remove_all_observers all_observers = key_observer_hash.clone key_observer_hash.keys.each do |key| remove_observers(key) end key_observer_hash.clear all_observers end |
#remove_observer(observer, key = nil) ⇒ Object
72 73 74 75 76 77 |
# File 'lib/glimmer/data_binding/observable_hash.rb', line 72 def remove_observer(observer, key = nil) if has_observer?(observer, key) key_observer_list(key).delete(observer) observer.unobserve(self, key) end end |
#remove_observers(key) ⇒ Object
79 80 81 82 83 84 |
# File 'lib/glimmer/data_binding/observable_hash.rb', line 79 def remove_observers(key) key_observer_hash[key].each do |observer| remove_observer(observer, key) end key_observer_hash.delete(key) end |
#store_method ⇒ Object
135 136 137 |
# File 'lib/glimmer/data_binding/observable_hash.rb', line 135 def store_method self.class.instance_method('[]=') rescue self.method('[]=') end |
#unregister_dependent_observers(key, old_value) ⇒ Object Also known as: deregister_dependent_observers
139 140 141 142 143 |
# File 'lib/glimmer/data_binding/observable_hash.rb', line 139 def unregister_dependent_observers(key, old_value) # TODO look into optimizing this return unless old_value.is_a?(ObservableModel) || old_value.is_a?(ObservableArray) || old_value.is_a?(ObservableHash) key_observer_list(key).each { |observer| observer.unregister_dependents_with_observable(observer.registration_for(self, key), old_value) } end |