Module: Glimmer::DataBinding::ObservableModel
- Includes:
- Observable
- Defined in:
- lib/glimmer/data_binding/observable_model.rb
Defined Under Namespace
Classes: Notifier
Constant Summary collapse
- PROPERTY_WRITER_FACTORY =
lambda do |property_name| property_writer_name = "#{property_name}=" lambda do |value| old_value = self.send(property_name) unregister_dependent_observers(property_name, old_value) # remove dependent observers previously installed in ensure_array_object_observer and ensure_hash_object_observer self.send("__original__#{property_writer_name}", value) notify_observers(property_name) ensure_array_object_observer(property_name, value, old_value) ensure_hash_object_observer(property_name, value, old_value) end end
Instance Method Summary collapse
- #add_observer(observer, property_name) ⇒ Object
- #add_property_writer_observers(property_name) ⇒ Object
- #array_object_observer_for(property_name) ⇒ Object
- #ensure_array_object_observer(property_name, object, old_object = nil) ⇒ Object
- #ensure_hash_object_observer(property_name, object, old_object = nil) ⇒ Object
- #has_observer?(observer, property_name) ⇒ Boolean
- #has_observer_for_any_property?(observer) ⇒ Boolean
- #hash_object_observer_for(property_name) ⇒ Object
- #notify_observers(property_name) ⇒ Object
- #property_observer_hash ⇒ Object
- #property_observer_list(property_name) ⇒ Object
- #property_writer_method(property_writer_name) ⇒ Object
- #remove_all_observers ⇒ Object
- #remove_observer(observer, property_name) ⇒ Object
- #remove_observers(property_name) ⇒ Object
- #unregister_dependent_observers(property_name, old_value) ⇒ Object (also: #deregister_dependent_observers)
Methods included from Observable
Instance Method Details
#add_observer(observer, property_name) ⇒ Object
55 56 57 58 59 60 |
# File 'lib/glimmer/data_binding/observable_model.rb', line 55 def add_observer(observer, property_name) return observer if has_observer?(observer, property_name) property_observer_list(property_name) << observer add_property_writer_observers(property_name) observer end |
#add_property_writer_observers(property_name) ⇒ Object
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/glimmer/data_binding/observable_model.rb', line 106 def add_property_writer_observers(property_name) property_writer_name = "#{property_name}=" method(property_writer_name) ensure_array_object_observer(property_name, send(property_name)) ensure_hash_object_observer(property_name, send(property_name)) begin method("__original__#{property_writer_name}") rescue define_singleton_method("__original__#{property_writer_name}", property_writer_method(property_writer_name)) define_singleton_method(property_writer_name, &PROPERTY_WRITER_FACTORY.call(property_name)) end rescue => e #ignore writing if no property writer exists Glimmer::Config.logger.debug {"No need to observe property writer: #{property_writer_name}\n#{e.}\n#{e.backtrace.join("\n")}"} end |
#array_object_observer_for(property_name) ⇒ Object
144 145 146 147 148 |
# File 'lib/glimmer/data_binding/observable_model.rb', line 144 def array_object_observer_for(property_name) @array_object_observers ||= Concurrent::Hash.new @array_object_observers[property_name] = ObservableModel::Notifier.new(self, property_name) unless @array_object_observers.has_key?(property_name) @array_object_observers[property_name] end |
#ensure_array_object_observer(property_name, object, old_object = nil) ⇒ Object
133 134 135 136 137 138 139 140 141 142 |
# File 'lib/glimmer/data_binding/observable_model.rb', line 133 def ensure_array_object_observer(property_name, object, old_object = nil) return unless object&.is_a?(Array) array_object_observer = array_object_observer_for(property_name) array_observer_registration = array_object_observer.observe(object) property_observer_list(property_name).each do |observer| my_registration = observer.registration_for(self, property_name) # TODO eliminate repetition observer.add_dependent(my_registration => array_observer_registration) end array_object_observer_for(property_name).unregister(old_object) if old_object.is_a?(ObservableArray) end |
#ensure_hash_object_observer(property_name, object, old_object = nil) ⇒ Object
150 151 152 153 154 155 156 157 158 159 |
# File 'lib/glimmer/data_binding/observable_model.rb', line 150 def ensure_hash_object_observer(property_name, object, old_object = nil) return unless object&.is_a?(Hash) hash_object_observer = hash_object_observer_for(property_name) hash_observer_registration = hash_object_observer.observe(object) property_observer_list(property_name).each do |observer| my_registration = observer.registration_for(self, property_name) # TODO eliminate repetition observer.add_dependent(my_registration => hash_observer_registration) end hash_object_observer_for(property_name).unregister(old_object) if old_object.is_a?(ObservableHash) end |
#has_observer?(observer, property_name) ⇒ Boolean
85 86 87 |
# File 'lib/glimmer/data_binding/observable_model.rb', line 85 def has_observer?(observer, property_name) property_observer_list(property_name).include?(observer) end |
#has_observer_for_any_property?(observer) ⇒ Boolean
89 90 91 |
# File 'lib/glimmer/data_binding/observable_model.rb', line 89 def has_observer_for_any_property?(observer) property_observer_hash.values.map(&:to_a).reduce(:+).include?(observer) end |
#hash_object_observer_for(property_name) ⇒ Object
161 162 163 164 165 |
# File 'lib/glimmer/data_binding/observable_model.rb', line 161 def hash_object_observer_for(property_name) @hash_object_observers ||= Concurrent::Hash.new @hash_object_observers[property_name] = ObservableModel::Notifier.new(self, property_name) unless @hash_object_observers.has_key?(property_name) @hash_object_observers[property_name] end |
#notify_observers(property_name) ⇒ Object
102 103 104 |
# File 'lib/glimmer/data_binding/observable_model.rb', line 102 def notify_observers(property_name) property_observer_list(property_name).to_a.each { |observer| observer.call(send(property_name)) } end |
#property_observer_hash ⇒ Object
93 94 95 |
# File 'lib/glimmer/data_binding/observable_model.rb', line 93 def property_observer_hash @property_observers ||= Hash.new end |
#property_observer_list(property_name) ⇒ Object
97 98 99 100 |
# File 'lib/glimmer/data_binding/observable_model.rb', line 97 def property_observer_list(property_name) property_observer_hash[property_name.to_sym] = Concurrent::Set.new unless property_observer_hash[property_name.to_sym] property_observer_hash[property_name.to_sym] end |
#property_writer_method(property_writer_name) ⇒ Object
122 123 124 |
# File 'lib/glimmer/data_binding/observable_model.rb', line 122 def property_writer_method(property_writer_name) self.class.instance_method(property_writer_name) rescue self.method(property_writer_name) end |
#remove_all_observers ⇒ Object
76 77 78 79 80 81 82 83 |
# File 'lib/glimmer/data_binding/observable_model.rb', line 76 def remove_all_observers all_observers = property_observer_hash.clone property_observer_hash.keys.each do |property_name| remove_observers(property_name) end property_observer_hash.clear all_observers end |
#remove_observer(observer, property_name) ⇒ Object
62 63 64 65 66 67 |
# File 'lib/glimmer/data_binding/observable_model.rb', line 62 def remove_observer(observer, property_name) if has_observer?(observer, property_name) property_observer_list(property_name).delete(observer) observer.unobserve(self, property_name) end end |
#remove_observers(property_name) ⇒ Object
69 70 71 72 73 74 |
# File 'lib/glimmer/data_binding/observable_model.rb', line 69 def remove_observers(property_name) property_observer_hash[property_name.to_sym].each do |observer| remove_observer(observer, property_name) end property_observer_hash.delete(property_name.to_sym) end |
#unregister_dependent_observers(property_name, old_value) ⇒ Object Also known as: deregister_dependent_observers
126 127 128 129 130 |
# File 'lib/glimmer/data_binding/observable_model.rb', line 126 def unregister_dependent_observers(property_name, old_value) # TODO look into optimizing this return unless old_value.is_a?(ObservableModel) || old_value.is_a?(ObservableArray) property_observer_list(property_name).each { |observer| observer.unregister_dependents_with_observable(observer.registration_for(self, property_name), old_value) } end |