Capturing access to array elements

Hi,

my question may sound a bit amateur, but I’m just starting to play
around with Ruby.

So which methods in Array do I have to override, if I want to make sure
I can capture any attempt to access an array element? In other words,
which are the Array methods which don’t rely on other ones to access
elements?

I haven’t found this mentioned in any documentation I came across.

thx
mortee

On Sep 18, 11:10 am, mortee [email protected] wrote:

So which methods in Array do I have to override, if I want to make sure
I can capture any attempt to access an array element? In other words,
which are the Array methods which don’t rely on other ones to access
elements?

Unfortunately, there isn’t a single method that accesses the value at
a particular index. For example, see the following code. Note that the
#[] method isn’t called by the other methods, including each. (Note
also that the following is not an exhaustive list, but does give you a
starting point for experimentally determining which method might call
others.)

a = %w| a b c |

def a.[]( *args, &blk )
p ‘[]’
super *args, &blk
end

def a.each( *args, &blk )
p ‘each’
super *args, &blk
end

def a.select( *args, &blk )
p ‘select’
super *args, &blk
end

def a.delete( *args, &blk )
p ‘delete’
super *args, &blk
end

def a.fetch( *args, &blk )
p ‘fetch’
super *args, &blk
end

puts “Using []:”
a[ 0 ]

puts “-”*40

puts “Using each:”
a.each{ |x| }

puts “-”*40

puts “Using select:”
a.select{ |x| }

puts “-”*40

puts “Using delete:”
a.delete ‘b’

puts “-”*40

puts “Using fetch:”
a.fetch 1

On 18.09.2007 20:47, Phrogz wrote:

starting point for experimentally determining which method might call
others.)

Having said that it’s probably easier to use Delegator to intercept
method calls. Maybe there’s also another approach to solving this.
Mortee, what are you trying to achieve?

Kind regards

robert

mortee wrote:

So which methods in Array do I have to override, if I want to make sure
I can capture any attempt to access an array element?

My chattr gem does this so it can do type-checking. It’s small, install
it and have a read.

Clifford H…

Unfortunately, there isn’t a single method that accesses the value at
a particular index. For example, see the following code. Note that the
#[] method isn’t called by the other methods, including each. (Note
also that the following is not an exhaustive list, but does give you a
starting point for experimentally determining which method might call
others.)

Having said that it’s probably easier to use Delegator to intercept
method calls. Maybe there’s also another approach to solving this.
Mortee, what are you trying to achieve?

Actually it’s indifferent if I use Delegator or not. In my scenario, I
get an array of record from a library function, and I want to have those
records automatically extended with a module’s methods, without any
extra work on the array’s user’s part (aside from once handling the
array itself).

But I don’t want to traverse the array right when I do this action in
question on the array: I’d like to leave it that to the time the
elements are actually accessed. This is because I want to have records
added to the array afterwards be extended also; and it may take
time-consuming actions for the “array” to fetch its elements, so I don’t
want to access them if not necessary.

That’s why I opted to override its element-accessor methods. I guess the
main principle would be the same whether I override the methods of the
array object in question itself, or I use a delegator object which wraps
the array’s methods (currently I use the latter, but I’d prefer the
former anyway).

mortee

2007/9/19, mortee [email protected]:

time-consuming actions for the “array” to fetch its elements, so I don’t
want to access them if not necessary.

That’s why I opted to override its element-accessor methods. I guess the
main principle would be the same whether I override the methods of the
array object in question itself, or I use a delegator object which wraps
the array’s methods (currently I use the latter, but I’d prefer the
former anyway).

Actually I believe the delegation approach (whether with Delegator or
other) is the superior approach. Although not with problems of its own
(object identity) wrapping something in order to control access to it
seems the most natural way to do it because there is no way left for
direct manipulation of the Array (yes, I know that you can work your
way around that). My 0.02 EUR.

Kind regards

robert

My chattr gem does this so it can do type-checking. It’s small, install
it and have a read.

It looks great, but it doesn’t seem to be applicable in my case. I have
to deal with arrays already created by a library function and returned
to me, so I can’t prescribe their actual class.

mortee

Robert K. wrote:

Actually I believe the delegation approach (whether with Delegator or
other) is the superior approach. Although not with problems of its own
(object identity) wrapping something in order to control access to it
seems the most natural way to do it because there is no way left for
direct manipulation of the Array (yes, I know that you can work your
way around that). My 0.02 EUR.

You’re right in a sense, and not in another. Currently, I use delegation
for the exact same reason you mention: I can control all access to the
underlying object.

But I’d also want to have my object as a fully capable Array, so I’d
have to cover all the Array methods anyway. And if that’s the case, I
may just override the object’s methods themselves just as well.

Delegation seemed slower to me than extending the object itself. But I
may be confused by some other factors - I haven’t done precise
measurements discarding any other influences.

mortee

Clifford H. wrote:

No, but you can re-open the class that they are of, and apply all
the methods from chattr, which replicates exactly the behaviour of
the standard Array class, so you know you haven’t broken anything
by interjecting.

Sounds possible. I’ll give it a try, thanks.

mortee

mortee wrote:

My chattr gem does this so it can do type-checking. It’s small, install
it and have a read.
It looks great, but it doesn’t seem to be applicable in my case. I have
to deal with arrays already created by a library function and returned
to me, so I can’t prescribe their actual class.

No, but you can re-open the class that they are of, and apply all
the methods from chattr, which replicates exactly the behaviour of
the standard Array class, so you know you haven’t broken anything
by interjecting.