Hi --
Hi,
I have a whole load of objects which I would like to periodically dump
as YAML. However, in order to save on resources, I would prefer to only
dump those whose instance variables have changed since the last dump.
Is it possible to somehow 'mark' an object when the value any of its
instance variables is changed?
I don't know whether this will be of practical use to you, but your
question got me wanting to brush up on Observable, so I did See
below. It probably threads a bit too narrow a needle, but maybe it
will give you some ideas. And if someone knows an existing shortcut
for this, let me know
I also recommend looking at observable.rb, in the standard libray,
just to see a great example of how powerful very simple Ruby can be.
require 'observer'
# A module which redefines attr_writer for classes that include it.
# The direct use of @observer_peers (the list of observers) is a bit
# inelegant, but I didn't want to keep adding the object watcher to
# the array over and over.
module AttrWriterInterceptor
def self.included(m)
m.class_eval do
include Observable
def self.attr_writer(*attrs)
attrs.each do |att|
define_method("#{att}=") do |value|
@observer_peers ||=
unless @observer_peers.include?(ObjectWatcher.instance)
add_observer(ObjectWatcher.instance)
end
instance_variable_set("@#{att}", value)
changed
notify_observers(self)
end
end
end
end
end
end
# A class that uses the observable attr_writers
class Item
include AttrWriterInterceptor
attr_writer :description
end
# A class to observe changes. It's a singleton to make it easier
# to add it as an observer (see above) without having to be passed
# an instance of it.
class ObjectWatcher
require 'singleton'
include Singleton
attr_accessor :changed
def initialize
self.changed = true
end
def update(obj)
self.changed = true
end
def dump_objects_if_changed
if self.changed
self.changed = false
"Dumping objects!"
else
"Not dumping objects!"
end
end
end
if __FILE__ == $0
require 'test/unit'
class ObserverTest < Test::Unit::TestCase
def setup
@ow = ObjectWatcher.instance
@i = Item.new
end
# Test dumping at the beginning, then make sure the second dump
# doesn't happen, then change an attr and make sure it does happen
# the third time.
def test_three_dumps
assert(@ow.changed)
assert_equal("Dumping objects!", @ow.dump_objects_if_changed)
assert(!@ow.changed)
assert_equal("Not dumping objects!", @ow.dump_objects_if_changed)
@i.description = "Some item"
assert(@ow.changed)
assert_equal("Dumping objects!", @ow.dump_objects_if_changed)
end
end
end
路路路
On Mon, 28 Aug 2006, Paul Murton wrote: