Module: Glimmer::DataBinding::ObservableModel

Includes:
Observable
Included in:
UI::CustomWidget
Defined in:
lib/glimmer/data_binding/observable_model.rb

Overview

TODO prefix utility methods with double-underscore

Defined Under Namespace

Classes: Notifier

Instance Method Summary collapse

Instance Method Details

#add_observer(observer, property_name) ⇒ Object



23
24
25
26
27
28
# File 'lib/glimmer/data_binding/observable_model.rb', line 23

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

TODO upon updating values, make sure dependent observers are cleared (not added as dependents here)



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/glimmer/data_binding/observable_model.rb', line 58

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))
  begin
    method("__original_#{property_writer_name}")
  rescue
    # TODO consider alias_method or define_method instead
    instance_eval "alias __original_#{property_writer_name} #{property_writer_name}"
    instance_eval <<-end_eval, __FILE__, __LINE__
    def #{property_writer_name}(value)
      old_value = self.#{property_name}
      unregister_dependent_observers('#{property_name}', old_value)
      self.__original_#{property_writer_name}(value)
      notify_observers('#{property_name}')
      ensure_array_object_observer('#{property_name}', value, old_value)
    end
    end_eval
  end
rescue => e
  # ignore writing if no property writer exists
  Glimmer.logger&.debug "No need to observe property writer: #{property_writer_name}\n#{e.message}\n#{e.backtrace.join("\n")}"
end

#array_object_observer_for(property_name) ⇒ Object



101
102
103
104
105
106
107
# File 'lib/glimmer/data_binding/observable_model.rb', line 101

def array_object_observer_for(property_name)
  @array_object_observers ||= {}
  unless @array_object_observers.has_key?(property_name)
    @array_object_observers[property_name] = ObservableModel::Notifier.new(self, property_name)
  end
  @array_object_observers[property_name]
end

#ensure_array_object_observer(property_name, object, old_object = nil) ⇒ Object



90
91
92
93
94
95
96
97
98
99
# File 'lib/glimmer/data_binding/observable_model.rb', line 90

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

#has_observer?(observer, property_name) ⇒ Boolean

Returns:

  • (Boolean)


34
35
36
# File 'lib/glimmer/data_binding/observable_model.rb', line 34

def has_observer?(observer, property_name)
  property_observer_list(property_name).include?(observer)
end

#has_observer_for_any_property?(observer) ⇒ Boolean

Returns:

  • (Boolean)


38
39
40
# File 'lib/glimmer/data_binding/observable_model.rb', line 38

def has_observer_for_any_property?(observer)
  property_observer_hash.values.map(&:to_a).sum.include?(observer)
end

#notify_observers(property_name) ⇒ Object



53
54
55
# File 'lib/glimmer/data_binding/observable_model.rb', line 53

def notify_observers(property_name)
  property_observer_list(property_name).each {|observer| observer.call(send(property_name))}
end

#property_observer_hashObject



42
43
44
45
46
# File 'lib/glimmer/data_binding/observable_model.rb', line 42

def property_observer_hash
  # TODO simplify with ||=
  @property_observers = Hash.new unless @property_observers
  @property_observers
end

#property_observer_list(property_name) ⇒ Object



48
49
50
51
# File 'lib/glimmer/data_binding/observable_model.rb', line 48

def property_observer_list(property_name)
  property_observer_hash[property_name.to_sym] = Set.new unless property_observer_hash[property_name.to_sym]
  property_observer_hash[property_name.to_sym]
end

#remove_observer(observer, property_name) ⇒ Object



30
31
32
# File 'lib/glimmer/data_binding/observable_model.rb', line 30

def remove_observer(observer, property_name)
  property_observer_list(property_name).delete(observer)
end

#unregister_dependent_observers(property_name, old_value) ⇒ Object



82
83
84
85
86
87
88
# File 'lib/glimmer/data_binding/observable_model.rb', line 82

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 do |observer|
    observer.unregister_dependents_with_observable(observer.registration_for(self, property_name), old_value)
  end
end