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)
    self.send("__original_#{property_writer_name}", value)
    notify_observers(property_name)
    ensure_array_object_observer(property_name, value, old_value)
  end
end

Instance Method Summary collapse

Methods included from Observable

#inspect

Instance Method Details

#add_observer(observer, property_name) ⇒ Object



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

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



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

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
    singleton_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.message}\n#{e.backtrace.join("\n")}"}
end

#array_object_observer_for(property_name) ⇒ Object



120
121
122
123
124
# File 'lib/glimmer/data_binding/observable_model.rb', line 120

def array_object_observer_for(property_name)
  @array_object_observers ||= {}        
  @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



109
110
111
112
113
114
115
116
117
118
# File 'lib/glimmer/data_binding/observable_model.rb', line 109

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)


63
64
65
# File 'lib/glimmer/data_binding/observable_model.rb', line 63

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

#has_observer_for_any_property?(observer) ⇒ Boolean

Returns:

  • (Boolean)


67
68
69
# File 'lib/glimmer/data_binding/observable_model.rb', line 67

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

#notify_observers(property_name) ⇒ Object



80
81
82
# File 'lib/glimmer/data_binding/observable_model.rb', line 80

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

#property_observer_hashObject



71
72
73
# File 'lib/glimmer/data_binding/observable_model.rb', line 71

def property_observer_hash
  @property_observers ||= Hash.new
end

#property_observer_list(property_name) ⇒ Object



75
76
77
78
# File 'lib/glimmer/data_binding/observable_model.rb', line 75

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

#property_writer_method(property_writer_name) ⇒ Object



99
100
101
# File 'lib/glimmer/data_binding/observable_model.rb', line 99

def property_writer_method(property_writer_name)
  self.class.instance_method(property_writer_name) rescue self.method(property_writer_name)      
end

#remove_observer(observer, property_name) ⇒ Object



59
60
61
# File 'lib/glimmer/data_binding/observable_model.rb', line 59

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

#unregister_dependent_observers(property_name, old_value) ⇒ Object



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

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