[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

[TIP] Proc as Observer

Tim Pease

11/8/2006 5:33:00 PM

Working with an Observable object, I wanted to be able to add a Proc
as an observer. Observable requires all observers to implement an
update method. When the Observable state changes, this is the method
that will be called to notify observers of the state change.

My generic solution was to create a module that adds an update method
for Proc objects.

module ProcAsObserver
def update( *args )
self.call *args
end
end

To use this module ...

method = lambda {|*args| args.each {|x| puts x}}
method.extend ProcAsObserver

my_observable_object.add_observer(method)

That's it! Just a handy little tip for anyone working with Observable objects.

Blessings,
TwP

20 Answers

Trans

11/8/2006 6:53:00 PM

0


Tim Pease wrote:
> Working with an Observable object, I wanted to be able to add a Proc
> as an observer. Observable requires all observers to implement an
> update method. When the Observable state changes, this is the method
> that will be called to notify observers of the state change.

Interesting... I'd like to see a simple example of this.

> My generic solution was to create a module that adds an update method
> for Proc objects.
>
> module ProcAsObserver
> def update( *args )
> self.call *args
> end
> end
>
> To use this module ...
>
> method = lambda {|*args| args.each {|x| puts x}}
> method.extend ProcAsObserver
>
> my_observable_object.add_observer(method)
>
> That's it! Just a handy little tip for anyone working with Observable objects.

Given your approach I think I'd just go ahead and do:

class Proc
alias :update :call
end

T.

Marcel Molina Jr.

11/8/2006 7:03:00 PM

0

On Thu, Nov 09, 2006 at 03:55:13AM +0900, Trans wrote:
> > my_observable_object.add_observer(method)
> >
> > That's it! Just a handy little tip for anyone working with Observable objects.
>
> Given your approach I think I'd just go ahead and do:
>
> class Proc
> alias :update :call
> end

In 1.9 the method signature of add_observer is:

def add_observer(observer, func=:update)

In your case, the second argument could be :call.

marcel
--
Marcel Molina Jr. <marcel@vernix.org>

Tim Pease

11/8/2006 7:15:00 PM

0

On 11/8/06, Marcel Molina Jr. <marcel@vernix.org> wrote:
> On Thu, Nov 09, 2006 at 03:55:13AM +0900, Trans wrote:
> > > my_observable_object.add_observer(method)
> > >
> > > That's it! Just a handy little tip for anyone working with Observable objects.
> >
> > Given your approach I think I'd just go ahead and do:
> >
> > class Proc
> > alias :update :call
> > end
>
> In 1.9 the method signature of add_observer is:
>
> def add_observer(observer, func=:update)
>
> In your case, the second argument could be :call.
>

Good to know. Thanks for the tip.

TwP

James Gray

11/8/2006 8:17:00 PM

0

On Nov 8, 2006, at 12:55 PM, Trans wrote:

> Given your approach I think I'd just go ahead and do:
>
> class Proc
> alias :update :call
> end

I thought Tim's solution was far more elegant. Notice how he
resisted gratuitous hacking of the core.

James Edward Gray II

Ara.T.Howard

11/8/2006 8:33:00 PM

0

Trans

11/8/2006 9:07:00 PM

0


ara.t.howard@noaa.gov wrote:
> On Thu, 9 Nov 2006, James Edward Gray II wrote:
>
> > On Nov 8, 2006, at 12:55 PM, Trans wrote:
> >
> >> Given your approach I think I'd just go ahead and do:
> >>
> >> class Proc
> >> alias :update :call
> >> end
> >
> > I thought Tim's solution was far more elegant. Notice how he resisted
> > gratuitous hacking of the core.
>
> not to mention tim's solution can be neatly extended to
>
> def observer &b
> o = lambda &b
> class << o
> alias_method 'update', 'call'
> end
> o
> end
>
> in fact, you'd thing add_observer would accept a block and do exactly this.
>
> regards.
>
> -a

I think that's over zealous about avoidance of core extension. This is
an excellent example of when a core extension is useful. Use of a
module and/or singleton here adds an additional layer of class
hierarchy that is simply unnecessary. There's nothing wrong with adding
#update to Proc in this case. I'm not sure why this general perception
of core extension as "hack" has gained so much footing. It's really
unfortunate since open classes are one the most unique and powerful
features of Ruby.

T.

Tim Pease

11/8/2006 9:32:00 PM

0

On 11/8/06, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> wrote:
>
> in fact, you'd thing add_observer would accept a block and do exactly this.
>

That's a fantastic idea. The only caveat is that the add_observer
method would need to return a reference to the created Proc object so
it can later be removed (if desired) using the delete_observer method.

I always forget that blocks can be passed around and turned into Procs.

TwP

Ara.T.Howard

11/8/2006 9:48:00 PM

0

Tim Pease

11/8/2006 10:26:00 PM

0

On 11/8/06, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> wrote:
>
> in fact, you'd thing add_observer would accept a block and do exactly this.
>

New and improved tip ...


class MyObservableClass
include Observable

def add_observer( observer = nil, &block )
unless block.nil?
observer = block.to_proc
class << observer
alias_method :update, :call
end
end
super observer
end
end


Now you can do this ...

observable = MyObservableClass.new
proc = observable.add_observer {|*args| puts args.inspect}

observable.delete_observer proc


I'm done posting about this now. Promise!

TwP

Trans

11/15/2006 1:24:00 AM

0


ara.t.howard@noaa.gov wrote:
> On Thu, 9 Nov 2006, Trans wrote:
>
> i'm sure not saying it's a bad idea, but i do avoid it when it's not needed
> and, here, it doesn't seem to be since the &b arg of add_observer is not
> currently used.

Cool. I agree with your there.

BTW, (*a, &b) is my new favorite way to express generic passthru
parameters. I'm tired of the old (*args, &blk) ;-)

T.