Skip to content

Instantly share code, notes, and snippets.

@davidjbeveridge
Created March 28, 2012 01:40
Show Gist options
  • Save davidjbeveridge/2222762 to your computer and use it in GitHub Desktop.
Save davidjbeveridge/2222762 to your computer and use it in GitHub Desktop.
Attribute Observers
module ObservableAttributes
module Observers
def observers
# A little hack to prevent the need for an @observers instance var
class << self
@observers ||= Hash.new
end
end
def bind event, property, &proc
event, property = event.to_sym, property.to_sym
observers[event] ||= Hash.new
observers[event][property] ||= Array.new
observers[event][property] << proc
end
end
module ClassMethods
include Observers
def attr_reader property
define_method property do
value = instance_variable_get :"@#{property}"
trigger :read, property.to_sym, value
value
end
end
def attr_writer property
define_method :"#{property}=" do |value|
instance_variable_set :"@#{property}", value
trigger :write, property.to_sym, value
end
end
def attr_accessor property
attr_reader property
attr_writer property
end
def testing
end
end # ClassMethods
module InstanceMethods
include Observers
def trigger method, property, value
all_available_observers = [observers, self.class.observers]
all_available_observers.each do |observer_hash|
if observer_hash.include? method
if observer_hash[method].include? property
observer_hash[method][property].each { |proc| proc.call(value) }
end
end
end
end
end # InstanceMethods
def self.included base
base.extend ClassMethods
base.send :include, InstanceMethods
end
end
class Person
include ObservableAttributes
attr_accessor :age
attr_accessor :name
end
Person.bind :write, :age do |value|
puts "Change observed by class"
end
david = Person.new
david.bind :write, :age do |value|
puts "Change observed by instance"
end
david.name = "David"
david.age = 25
p david
@mrgenixus
Copy link

I think this does more than I need; I can't figure out what parts I need, exactly. Basically, I just want to bind attr_* to a database backend.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment