Module: Glimmer::DataBinding::ObservableModel

Includes:
Observable
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



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

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)



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

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
    old_method = self.class.instance_method(property_writer_name)
    define_singleton_method("__original_#{property_writer_name}", old_method)
    define_singleton_method(property_writer_name) do |value|
      old_value = self.send(property_name)
      unregister_dependent_observers(property_name, old_value)
      self.send("__original_#{property_writer_name}", value)
      notify_observers(property_name)
      ensure_array_object_observer(property_name, value, old_value)
    end
  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



95
96
97
98
99
100
101
# File 'lib/glimmer/data_binding/observable_model.rb', line 95

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



84
85
86
87
88
89
90
91
92
93
# File 'lib/glimmer/data_binding/observable_model.rb', line 84

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)


32
33
34
# File 'lib/glimmer/data_binding/observable_model.rb', line 32

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

#has_observer_for_any_property?(observer) ⇒ Boolean

Returns:

  • (Boolean)


36
37
38
# File 'lib/glimmer/data_binding/observable_model.rb', line 36

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

#notify_observers(property_name) ⇒ Object



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

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

#property_observer_hashObject



40
41
42
# File 'lib/glimmer/data_binding/observable_model.rb', line 40

def property_observer_hash
  @property_observers ||= Hash.new
end

#property_observer_list(property_name) ⇒ Object



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

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



28
29
30
# File 'lib/glimmer/data_binding/observable_model.rb', line 28

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

#unregister_dependent_observers(property_name, old_value) ⇒ Object



76
77
78
79
80
81
82
# File 'lib/glimmer/data_binding/observable_model.rb', line 76

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