module Glimmer::DataBinding::Observer

Mixin representing Observer trait from Observer Design Pattern Allows classes to include without interfering with their inheritance hierarchy.

Includes a default implementation that can receive an observer block Example: Observer.proc {|new_value| puts new_value} Subclasses may override

Constants

Registration

Public Class Methods

proc(&observer_block) click to toggle source
# File lib/glimmer/data_binding/observer.rb, line 58
def proc(&observer_block)
  Proc.new(&observer_block)
end

Public Instance Methods

add_dependent(parent_to_dependent_hash) click to toggle source

add dependent observer to unregister when unregistering observer

# File lib/glimmer/data_binding/observer.rb, line 141
def add_dependent(parent_to_dependent_hash)
  registration = parent_to_dependent_hash.keys.first
  dependent = parent_to_dependent_hash.values.first
  dependents_for(registration) << dependent
end
call(new_value = nil, *extra_args) click to toggle source
# File lib/glimmer/data_binding/observer.rb, line 155
def call(new_value = nil, *extra_args)
  raise Error, 'Not implemented!'
end
compact_args(args) click to toggle source
# File lib/glimmer/data_binding/observer.rb, line 159
def compact_args(args)
  args = args[0...-1] if args.last == {}
  args = args[0...-1] if args.last == []
  args.compact
end
dependents() click to toggle source

mapping of registrations to dependents {[observable, property] => [[dependent, dependent_observable, dependent_property], …]}

# File lib/glimmer/data_binding/observer.rb, line 75
def dependents
  @dependents ||= Concurrent::Hash.new
end
dependents_for(registration) click to toggle source
# File lib/glimmer/data_binding/observer.rb, line 79
def dependents_for(registration)
  dependents[registration.object_id] ||= Concurrent::Set.new
end
deregister(observable, *args)
Alias for: unobserve
deregister_all_observables()
deregister_dependents_with_observable(registration, dependent_observable)
ensure_registration_for!(observable, *args)
Alias for: registration_for
observe(observable, *args) click to toggle source

registers observer in an observable on args usually containing a property and options (optional) observer maintains registration list to unregister later

# File lib/glimmer/data_binding/observer.rb, line 85
def observe(observable, *args)
  options = args.last.is_a?(Hash) ? args.last : {}
  return if observable.nil?
  return if options[:ignore_frozen] && observable.frozen?
  unless observable.is_a?(Observable)
    # TODO refactor code to be more smart/polymorphic/automated and honor open/closed principle (e.g. for SomeClass, search if there is ObservableSomeClass)
    if observable.is_a?(Array)
      observable.extend(ObservableArray)
    elsif observable.is_a?(Hash)
      observable.extend(ObservableHash)
    else
      observable.extend(ObservableModel)
    end
  end
  args = compact_args(args)
  observable.add_observer(self, *args)
  ensure_registration_for!(observable, *args)
end
Also aliased as: register
register(observable, *args)
Alias for: observe
registration_for(observable, *args) click to toggle source
# File lib/glimmer/data_binding/observer.rb, line 67
def registration_for(observable, *args)
  args = compact_args(args)
  registrations[[observable.object_id, args]] ||= Registration.new(observer: self, observable: observable, args: args)
end
Also aliased as: ensure_registration_for!
registrations() click to toggle source
# File lib/glimmer/data_binding/observer.rb, line 63
def registrations
  @registrations ||= Concurrent::Hash.new
end
remove_dependent(parent_to_dependent_hash) click to toggle source
# File lib/glimmer/data_binding/observer.rb, line 147
def remove_dependent(parent_to_dependent_hash)
  registration = parent_to_dependent_hash.keys.first
  dependent = parent_to_dependent_hash.values.first
  dependents_for(registration).delete(dependent).tap do
    dependents.delete([registration.object_id]) if dependents_for(registration).empty?
  end
end
unobserve(observable, *args) click to toggle source
# File lib/glimmer/data_binding/observer.rb, line 105
def unobserve(observable, *args)
  return unless observable.is_a?(Observable)
  args = compact_args(args)
  registration = registration_for(observable, *args)
  registrations.delete([observable.object_id, args])
  registration.tap do |registration|
    dependents_for(registration).each do |dependent|
      remove_dependent(registration => dependent)
      dependent.deregister if dependent != registration
    end
    observable.remove_observer(self, *args)
  end
end
Also aliased as: unregister, deregister
unobserve_all_observables() click to toggle source

cleans up all registrations in observables

# File lib/glimmer/data_binding/observer.rb, line 131
def unobserve_all_observables
  registrations.values.dup.each do |registration|
    registration.deregister
    registrations.delete([registration.observable.object_id, registration.args])
  end
end
unobserve_dependents_with_observable(registration, dependent_observable) click to toggle source
# File lib/glimmer/data_binding/observer.rb, line 121
def unobserve_dependents_with_observable(registration, dependent_observable)
  thedependents = dependents_for(registration).select do |thedependent|
    thedependent.observable == dependent_observable
  end
  thedependents.each(&:deregister)
end
unregister(observable, *args)
Alias for: unobserve
unregister_all_observables()
unregister_dependents_with_observable(registration, dependent_observable)