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

Methods included from Observable

#inspect

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)



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

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::Config.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



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

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



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

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



51
52
53
# File 'lib/glimmer/data_binding/observable_model.rb', line 51

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

#property_observer_hashObject



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

def property_observer_hash
  @property_observers ||= Hash.new
end

#property_observer_list(property_name) ⇒ Object



46
47
48
49
# File 'lib/glimmer/data_binding/observable_model.rb', line 46

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



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

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