Forum: Ruby Calling an arbitrary method as and when an array's contents

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Dan Stevens (IAmAI) (Guest)
on 2007-07-06 02:14
(Received via mailing list)
I have a collection class that extends the Array class and I wish to
have a particular method to be called whenever the contents of an
instance of the class change. Can anyone advise on how I can achieve
this?

I'm aware that I can compare #hash with a previous saved value to
determine if the contents of the instance have changed since the last
time #hash was called. Therefore, if I can find a means of calling an
arbitrary method or piece of code every time any method is called on
the instance, I could achieve what I'm after. Can I override
Object#send?
MenTaLguY (Guest)
on 2007-07-06 02:28
(Received via mailing list)
On Fri, 6 Jul 2007 07:13:31 +0900, "Dan Stevens (IAmAI)"
<removed_email_address@domain.invalid> wrote:
> I have a collection class that extends the Array class and I wish to
> have a particular method to be called whenever the contents of an
> instance of the class change. Can anyone advise on how I can achieve
> this?

For this purpose, it's probably better to wrap/delegate to Array than
extend it.

That way, you can have control of all the methods that change something,
and
guarantee that they will perform the appropriate notification.  I'd also
recommend looking at Observer for the notification of the equation.

-mental
Micah M. (Guest)
on 2007-07-06 02:58
(Received via mailing list)
Great.  Houlihans is quiet enough for us to talk. 5:00pm work for you?

Sent from my iPhone
Gregory B. (Guest)
on 2007-07-06 03:02
(Received via mailing list)
On 7/5/07, Dan Stevens (IAmAI) <removed_email_address@domain.invalid> wrote:
> Object#send?
It sounds like you might be able to set up something like this with
Observer.
http://www.ruby-doc.org/stdlib/libdoc/observer/rdo...
unknown (Guest)
on 2007-07-06 03:02
(Received via mailing list)
Hi --

On Fri, 6 Jul 2007, Micah M. wrote:

> Great.  Houlihans is quiet enough for us to talk. 5:00pm work for you?

You forgot to tell us which Houlihans :-)


David
James G. (Guest)
on 2007-07-06 03:04
(Received via mailing list)
On Jul 5, 2007, at 5:57 PM, Micah M. wrote:

> Great.  Houlihans is quiet enough for us to talk. 5:00pm work for you?

We will be there!

Be sure to grab a big enough table to hold us.  A few thousand will
be fine.

> Sent from my iPhone

Does it help you see _who_ you are sending messages to by chance?  ;)

James Edward G. II
Dan Stevens (IAmAI) (Guest)
on 2007-07-06 03:05
(Received via mailing list)
> Ah! I'd forgotten about the observer pattern. That should do the trick. Thanks!

After looking at the Observable module, it only really solves half of
my problem. While it's a nice mechanism for notify observers that an
object has changed, it does help me determine whether or not an object
has changed; it leaves that up to the programmer.

> For this purpose, it's probably better to wrap/delegate to Array than extend it.

This is a potential solution - I could override all the methods of the
Array class that I think modify the contents of the Array in a
superclass, calling Observable#changed before/after calling the
parent's method. However, what if I think there's one too many methods
to be overriding or a forget to override one?

Truth is, I've now realised that I actually don't *need* an answer to
this question to solve my problem (helps to have full insight into
one's problems first). However, for the sake of argument and my
curiosity, does anyone thing there's an easier and more reliable
solution?
unknown (Guest)
on 2007-07-06 03:15
(Received via mailing list)
Hi --

On Fri, 6 Jul 2007, James Edward G. II wrote:

> Does it help you see _who_ you are sending messages to by chance?  ;)
Hey, it's only the first iteration of the iPhone -- you can't expect
all the bells and whistles yet :-)


David
Gregory B. (Guest)
on 2007-07-06 03:27
(Received via mailing list)
On 7/5/07, Dan Stevens (IAmAI) <removed_email_address@domain.invalid> wrote:
> Array class that I think modify the contents of the Array in a
> superclass, calling Observable#changed before/after calling the
> parent's method. However, what if I think there's one too many methods
> to be overriding or a forget to override one?

Um.... do you really need an observable array or are you building an
object that uses an array under the hood that needs to be observable?
 Big difference there.

In the former case, you'll likely want to use a blank slate proxy that
does the notification on delegation.  On the latter case it's really
easy, just notify on the methods you're actually using. :)

Word on the street is that subclassing core classes to change
behaviour is a bad idea anyway.  You might risk your subclass methods
not getting called in favor of the C methods being called without you
knowing...
Gregory B. (Guest)
on 2007-07-06 03:31
(Received via mailing list)
On 7/5/07, Micah M. <removed_email_address@domain.invalid> wrote:
> Great.  Houlihans is quiet enough for us to talk. 5:00pm work for you?

I changed my mind. Red Lobster is better.
unknown (Guest)
on 2007-07-06 03:38
(Received via mailing list)
Hi --

On Fri, 6 Jul 2007, Gregory B. wrote:

> On 7/5/07, Micah M. <removed_email_address@domain.invalid> wrote:
>> Great.  Houlihans is quiet enough for us to talk. 5:00pm work for you?
>
> I changed my mind. Red Lobster is better.

I vote for Ruby Tuesday.


David
James G. (Guest)
on 2007-07-06 04:00
(Received via mailing list)
On Jul 5, 2007, at 6:04 PM, Dan Stevens (IAmAI) wrote:

>> For this purpose, it's probably better to wrap/delegate to Array
>> than extend it.
>
> This is a potential solution - I could override all the methods of the
> Array class that I think modify the contents of the Array in a
> superclass, calling Observable#changed before/after calling the
> parent's method. However, what if I think there's one too many methods
> to be overriding or a forget to override one?

It's really not too much work:

#!/usr/bin/env ruby -wKU

require "observer"

class OArray
   instance_methods.each { |meth| undef_method(meth) unless meth =~ /
\A__/ }

   include Observable

   def initialize(array)
     @array = array
   end

   def method_missing(meth, *args, &block)
     @array.send(meth, *args, &block)

     if %w{ []= clear concat delete delete_at
            delete_if fill pop push replace shift }.include?
(meth.to_s) or
        meth.to_s[-1] == ?!
       changed
       notify_observers(@array, meth, *args, &block)
     end
   end
end

class Array
   def to_oarray
     OArray.new(self)
   end
end

observer = Object.new
class << observer
   def update(array, *call)
     puts "You called #{call.first} and the Array is now #
{array.inspect}."
   end
end

observed = [1, 2, 3].to_oarray
observed.add_observer(observer)
observed[1]
observed[1] = "2"

__END__

James Edward G. II
Todd B. (Guest)
on 2007-07-06 04:02
(Received via mailing list)
On 7/5/07, removed_email_address@domain.invalid 
<removed_email_address@domain.invalid> wrote:
> Hi --
>
> On Fri, 6 Jul 2007, Micah M. wrote:
>
> > Great.  Houlihans is quiet enough for us to talk. 5:00pm work for you?
>
> You forgot to tell us which Houlihans :-)
>
>
> David

You think this will be a common iPhone thing?
Todd B. (Guest)
on 2007-07-06 04:03
(Received via mailing list)
On 7/5/07, removed_email_address@domain.invalid 
<removed_email_address@domain.invalid> wrote:
>
>
> David

Yeah, Houlihans might be at Bennigan's.
Gregory B. (Guest)
on 2007-07-06 04:12
(Received via mailing list)
On 7/5/07, Todd B. <removed_email_address@domain.invalid> wrote:
> > David
>
> You think this will be a common iPhone thing?

Maybe that's a clever marketing ploy.  Apple has joined forces with
Houlihans!
Chris C. (Guest)
on 2007-07-06 08:34
(Received via mailing list)
On 7/5/07, Gregory B. <removed_email_address@domain.invalid> wrote:
> Maybe that's a clever marketing ploy.  Apple has joined forces with Houlihans!

First Google, then AT&T, and now Houlihans!  The trifecta of evil
corporation partnerships is complete!  Our world is going to be taken
over!  I for one welcome our stylish, heavily indexed, delicious
tasting, cellular providing overlords!
Dan Stevens (IAmAI) (Guest)
on 2007-07-06 11:11
(Received via mailing list)
I contemplated using the #hash method to determine if the array had
changed:

[snip]

  def method_missing(meth, *args, &block)
    @last_hash = @array.hash
    @array.send(meth, *args, &block)
    if @array.hash != @last_hash
      changed
      notify_observers(@array, meth, *args, &block)
    end
  end

[snip]

That way I don't have to worry about which methods change the contents
of the array.
Dan Stevens (IAmAI) (Guest)
on 2007-09-26 01:08
(Received via mailing list)
> It sounds like you might be able to set up something like this with Observer.

Ah! I'd forgotten about the observer pattern. That should do the trick.
Thanks!
This topic is locked and can not be replied to.