# KVO in Ruby

**URL:** <https://www.ruby-forum.com/t/kvo-in-ruby/106184>\
**Category:** Ruby\
**Created:** [June 7, 2007, 7:47am UTC](https://www.ruby-forum.com/t/kvo-in-ruby/106184 "2007-06-07T07:47:13Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![jballanc](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/97f17d/32.png) [@jballanc](https://www.ruby-forum.com/u/jballanc)\
**Post date:** [June 7, 2007, 7:47am UTC](https://www.ruby-forum.com/t/kvo-in-ruby/106184/1 "2007-06-07T07:47:13Z")

</div>

Hey all!

I’m still relatively new to Ruby, so forgive me if this seems like a  
naive (or even stupid) question, but…

Is there a good method for implementing Key-Value Observing in Ruby?

Basically, what I’d like to be able to do is this:

class Actor  
attr\_accessor :var\_to\_change

def change\_var  
@var\_to\_change = 1  
100.times {@var\_to\_change += 1}  
end  
end

class Observer  
def initialize(act)  
@actor = act  
act.add\_observer(self, var\_to\_change)  
end

def observeValue(var, sender)  
if sender == @actor  
puts “The value is now #{var}”  
end  
end  
end

act = Actor.new  
obs = Observer.new(act)  
thr = Thread.new {act.change\_var}  
thr.join

The resulting output would be:  
The value is now 1  
The value is now 2  
…and so on.

I realize that there are all sorts of ways that similar functionality  
could be achieved, but something about KVO is really attractive  
(especially since Ruby is already really good at KVC). It seems to me  
that this would be a fairly easy to implement as a module, but I don’t  
want to have to do the work if someone else already has. Does anyone  
know how RubyCocoa handles KVO? or if it does?

Thanks for any help/comments/scornful rebukes. 😉

-Josh

---

<div class="post-metadata">

**Author:** ![jballanc](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/97f17d/32.png) [@jballanc](https://www.ruby-forum.com/u/jballanc)\
**Post date:** [June 7, 2007, 8:01am UTC](https://www.ruby-forum.com/t/kvo-in-ruby/106184/2 "2007-06-07T08:01:21Z")

</div>

On Jun 6, 2007, at 10:47 PM, Joshua B. wrote:

> Hey all!  
> Hey

> Is there a good method for implementing Key-Value Observing in Ruby?  
> Check out the Observable module.

[http://ruby-doc.org/core/classes/Observable.html](http://ruby-doc.org/core/classes/Observable.html)

---

<div class="post-metadata">

**Author:** ![jballanc](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/97f17d/32.png) [@jballanc](https://www.ruby-forum.com/u/jballanc)\
**Post date:** [June 7, 2007, 4:53pm UTC](https://www.ruby-forum.com/t/kvo-in-ruby/106184/3 "2007-06-07T16:53:44Z")

</div>

Zachary H. wrote:

> On Jun 6, 2007, at 10:47 PM, Joshua B. wrote:
> 
> > Hey all!  
> > Hey
> 
> > Is there a good method for implementing Key-Value Observing in Ruby?  
> > Check out the Observable module.
> 
> [http://ruby-doc.org/core/classes/Observable.html](http://ruby-doc.org/core/classes/Observable.html)

Hmm…how did I miss that? This should do very well for the project I’m  
currently working on.

However, looking through the Observable module, I see one major  
downside: it’s not automatic. That is, the Observable module should work  
well enough for custom classes, but what about Built-in and Standard  
Library classes? If, say, you wanted to be notified when the length of a  
string was changed, you would have to extend the String class, but then  
also implement a method to constantly observe the length…or am I  
missing something here? The way I understand how this works in Cocoa is  
that isa-swizzling is used to replace the class of the property being  
observed with a thin pseudo-class that notifies any registered observers  
when a change is made, then passes the change to the original class.

Is there a good reason not to do things this way? to do things this way?  
The only KVO implementation that I’ve ever used is Cocoa’s, so I’m just  
curious about how/why it’s done in Ruby. If I’m making a big fuss over  
nothing please feel free to say so.

---

<div class="post-metadata">

**Author:** ![jballanc](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/97f17d/32.png) [@jballanc](https://www.ruby-forum.com/u/jballanc)\
**Post date:** [June 7, 2007, 8:04pm UTC](https://www.ruby-forum.com/t/kvo-in-ruby/106184/4 "2007-06-07T20:04:13Z")

</div>

Joshua B. wrote:

> that isa-swizzling is used to replace the class of the property being  
> observed with a thin pseudo-class that notifies any registered observers  
> when a change is made, then passes the change to the original class.
> 
> Is there a good reason not to do things this way? to do things this way?  
> The only KVO implementation that I’ve ever used is Cocoa’s, so I’m just  
> curious about how/why it’s done in Ruby. If I’m making a big fuss over  
> nothing please feel free to say so.

It will be difficult to get automatic notification of a change in the  
length of a string, since there are so many ways that can happen, and it  
happens in core code. (For example, the C function rb\_str\_append() gets  
called from other C functions, so there is no way to hook in a pure ruby  
observer.)

However, there are some cases where a library class has an attr\_writer  
(or other method) and all you want is notification of changes that go  
through that method. And, of course if you are developing the library  
yourself you can force all changes to go through a method.

In these cases, you might want to take a look at my observable library  
(really, it should be called observable-attr or something):

[http://raa.ruby-lang.org/project/observable/](http://raa.ruby-lang.org/project/observable/)  
[http://redshift.sourceforge.net/observable/](http://redshift.sourceforge.net/observable/)

Unlike the standard Observer library, which operates at the level of  
entire objects, this library operates on individual methods. Also,  
notification is automatic in the sense that the observed object doesn’t  
have to call notify\_observers. Further, each observer can register more  
than one “when” clause that is called just when the new value matches  
(in the sense of #===) some pattern, class, or other matching object.

I’ve found this useful primarily in fxruby (the foxtails library uses it  
to make data targets more friendly and responsive).

Here’s an example:

require ‘observable’

# A prexisting class with a method that doesn’t expect to be

observed.  
class Base  
attr\_writer :foo  
end

class Speaker \< Base  
extend Observable

```
 # make the inherited method :foo be observable and define an
 # additional observable attribute, :bar.
 observable :foo, :bar

 def run
   self.foo = "1"
   self.bar = [4,5,6]
   self.foo = "2"
   self.bar << 7 # Caution: no notification here!
   self.bar += [8] # notification
   self.foo = "3"
   @foo = "4" # No notification here, since writer wasn't called
 end

```

end

class Listener  
def initialize(speaker)  
speaker.when\_foo /2/ do |v|  
puts “#{self} saw foo change to have a 2 in #{v.inspect}”  
end

```
   speaker.when_foo /\d/ do |v|
     puts "#{self} saw foo change to have a digit in #{v.inspect}"
   end

   # This would override the first when_foo clause
   #speaker.when_foo /2/ do |v|
   # puts "#{self} saw foo change to have a 2 in #{v.inspect}

```

[overridden]"  
#end

```
   # listen for _any_ changes (note that #=== is used to match 

```

value,  
# so Object matches everything, including the initial nil)  
speaker.when\_bar Object do |v, old\_v|  
puts “#{self} saw bar change from #{old\_v.inspect} to  
#{v.inspect}”  
end  
end  
end

sp = Speaker.new  
Listener.new(sp)  
sp.run

**END**

Output:

#Listener:0xb7a56628 saw bar change from nil to nil  
#Listener:0xb7a56628 saw foo change to have a digit in “1”  
#Listener:0xb7a56628 saw bar change from nil to [4, 5, 6]  
#Listener:0xb7a56628 saw foo change to have a 2 in “2”  
#Listener:0xb7a56628 saw foo change to have a digit in “2”  
#Listener:0xb7a56628 saw bar change from [4, 5, 6, 7] to [4, 5, 6, 7,  
8]  
#Listener:0xb7a56628 saw foo change to have a digit in “3”

---

<div class="post-metadata">

**Author:** ![jballanc](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/97f17d/32.png) [@jballanc](https://www.ruby-forum.com/u/jballanc)\
**Post date:** [June 7, 2007, 8:15pm UTC](https://www.ruby-forum.com/t/kvo-in-ruby/106184/5 "2007-06-07T20:15:15Z")

</div>

On Jun 7, 2007, at 7:53 AM, Joshua B. wrote:

> string was changed, you would have to extend the String class, but  
> then  
> also implement a method to constantly observe the length…or am I  
> missing something here?  
> I suppose you wouldn’t have to modify the String class, if you just  
> want to observe one string.

require ‘observer’

s = “Something fishy”  
class \<\< s  
include( Observable )  
#etc…  
end

> The way I understand how this works in Cocoa is  
> that isa-swizzling is used to replace the class of the property being  
> observed with a thin pseudo-class that notifies any registered  
> observers  
> when a change is made, then passes the change to the original class.  
> Could be. It’s been a while since I played with NSAnything.

> Is there a good reason not to do things this way? to do things this  
> way?  
> The only KVO implementation that I’ve ever used is Cocoa’s, so I’m  
> just  
> curious about how/why it’s done in Ruby. If I’m making a big fuss over  
> nothing please feel free to say so.  
> You could do something like this. I’m not sure whether masking the  
> class like this is kosher, however. It would take some tinkering to  
> make it work with more complex classes, but you get the idea.

require ‘observer’

class Observee  
include Observable  
def initialize( thing )  
@thing = thing  
end  
def method\_missing( meth, \*args )  
changed true  
notify\_observers( meth, @thing.dup, @thing.send( meth, \*args ) )  
end  
def class ; @thing.class ; end  
end

class Observer  
def update( meth, ol, ne )  
puts “#{meth} #{  
ol == ne ? ‘did not change’ : ‘changed’  
} the #{ol.class.name}”  
end  
end

s = Observee.new( “Something fishy” )  
puts s.class.name  
so = Observer.new  
s.add\_observer( so )  
s.gsub!( /([aeiouy])/, ‘Y’ )  
s \<\< ’ Mmm. Tasty’  
s.gsub!( /([aeiouy])/, ‘’ )

h = Observee.new( :a =\> ‘b’ )  
puts h.class.name  
ho = Observer.new  
h.add\_observer( ho )  
h[:c] = ‘d’  
h.delete( :a )
