Is there a hook that is called whenever an instance variable

I’m developing an editing application with full undo/redo, so my
objects must log all changes to a history that can be rolled backwards
and forwards. This is just crying out for some fancy metaprogramming,
and it would be really neat if I could insert some code that is called
whenever an object assigns an instance variable. Is there anything
like that?

Regards,

Jeremy H.

On 11/19/06, Jeremy H. [email protected] wrote:

I’m developing an editing application with full undo/redo, so my
objects must log all changes to a history that can be rolled backwards
and forwards. This is just crying out for some fancy metaprogramming,
and it would be really neat if I could insert some code that is called
whenever an object assigns an instance variable. Is there anything
like that?

Regards,

Jeremy H.

I’m not aware of any hooks for instance variables, but as long as
you’re setting everything using setter methods or attr_accessor you
can just hook into all methods ending in a “=”.

class A
attr_accessor :a, :b
instance_methods(false).each{|m|
alias_method “orig_#{m}”,m
define_method(m){|*args|
puts “called #{m}”
send(“orig_#{m}”,*args)
} if m[-1] == ?=
}
end

o = A.new
o.a=[4, 8, 15, 16, 23] # => called a=
o.b=42 # => called b=

puts o.b # just 42, without any “called b”

On 2006-11-19, Sander L. [email protected] wrote:

attr_accessor :a, :b
instance_methods(false).each{|m|
alias_method “orig_#{m}”,m
define_method(m){|*args|
puts “called #{m}”
send(“orig_#{m}”,*args)
} if m[-1] == ?=
}
end

Nice! My mind boggled a little over “if m[-1] == ?=” but I get it
now. I guess the industrial strength solution would be a mixin that
when included into Foo: (a) hooks all existing Foo#= methods as you
do above, (b) defines Foo#method_added to hook all Foo#
= methods that
are subsequently def’ed, (c) defines Foo#method_missing to handle
Foo#*= methods similarly.

Of course this assumes only *= methods change the object, which is not
true of Hash, Array etc. I guess what I really want is an
Object#object_changed hook.

Regards,

Jeremy H.

On 11/21/06, Jeremy H. [email protected] wrote:

On 2006-11-19, Sander L. [email protected] wrote:

On 11/19/06, Jeremy H. [email protected] wrote:

… it would be really neat if I could insert some code that is
called whenever an object assigns an instance variable. Is there
anything like that?

If you grep through the mailing list for “Observing changes in object
state” you’ll find two different solutions to the problem - longish
posts, so I won’t repeat them here.

Cheers,
Max