Aop in ruby

hello!

im currently working on a aop library for ruby. most of the things like pointcuts and
joinpoints work fairly well. unfortunately i can not find a elegant solution for something:

- it must be possible to pass objects which have aspects weaved around without
running into a deadlock, this is especially important for passing them to advices.

- advices must be also working when methods of the object are called by the
object itself.

basically i see two possibilities:

1) via a proxy, which holds the original object, creates each method existing on
the original object for the proxy. something like:

def foo
  SomeAspect.before...
  @object.foo
end
(totally oversimplified, i know =)

2) via rewriting the methods on the object itself. weaving in the advices
directly and just calling the original method via the id..

the problem is that neither of those possibilities solve both problems.
the first one makes it impossible that advices are applied when methods
are called from within the object itself, since the method is not called via
the proxy.. (is it possible to do something nasty like redefining 'self' for
a object? =)

the second one can lead to quite serious trouble, because there is no way
to guarantee that the method is called without any advices (for example by
advices themself)

is there any other possibility to solve this in ruby? amy i overseeing something?

thanks a lot for any tipp!

ciao!
florian

Florian Weber wrote:

hello!

im currently working on a aop library for ruby. most of the things like pointcuts and
joinpoints work fairly well. unfortunately i can not find a elegant solution for something:

Well, I have no idea what aop is, but I showed the following code to a friend, and he said it looked like aop. I just wanted something to easily add scripting to an application. Add multiple "filters" to the arguments or result of any method. I wrote it this evening, so there could be some bugs in it. But maybe this will be usefull to you:

class Class
  def add_hook(method)
   self.module_eval("
    alias_method :#{method}_old, :#{method}

    @@pre_#{method} =
    @@post_#{method} =

    def #{method}(*args)
     @@pre_#{method}.map {|block| *args = block.call(*args)}
     result = #{method}_old *args
     @@post_#{method}.map {|block| result = block.call(result)}
     result
    end

    def #{name}.add_pre_#{method}(&block)
     @@pre_#{method}.push(block)
    end

    def #{name}.add_post_#{method}(&block)
     @@post_#{method}.push(block)
    end
   ")
  end
end

# Example code
class Hello
  def foobar(a,b,c)
   a + b + c
  end
end

o = Hello.new
puts o.foobar(" a ", " b ", " c ")
Hello.add_hook("foobar")
Hello.add_pre_foobar {|a,b,c| [a," change middle argument ",c]}
Hello.add_post_foobar{|res| res + " add something to result"}
puts o.foobar(" a ", " b ", " c ")
puts o.foobar_old(" a ", " b ", " c ")
Hello.add_pre_foobar {|a,b,c| [a,b,"change last one too"]}
puts o.foobar("1","2","3")

mh.. two things.
First: did you already looked at AspectR, the prior hack from (IIRC)
Robert Feldt, and the defadvice from mauricio fernandez [3]

Second:
what your #2 problem mean?
I'm not an AOP expert at all, but why you'd need to call the base
method without any aspects? I thought that every pre and post thingy
should be forced to work with the other, am I wrong?

[1] aspectr.sourceforge.ne
[2] sorry don't have a link handy :confused:
[3] http://www.thekode.net/ruby/techniques/CapturingMethods.html

···

il Thu, 22 Jul 2004 06:34:54 +0900, Florian Weber <csshsh@structbench.com> ha scritto::

is there any other possibility to solve this in ruby? amy i overseeing
something?

is there any other possibility to solve this in ruby? amy i overseeing
something?

mh.. two things.
First: did you already looked at AspectR, the prior hack from (IIRC)
Robert Feldt, and the defadvice from mauricio fernandez [3]

yes. i checked out aspectr. its quite great. there are a couple of things
which i dont like about it. but it definatelly helps a lot.

however it has the same issues. its not possible to pass the a
advice-free object to the advices.

Second:
what your #2 problem mean?
I'm not an AOP expert at all, but why you'd need to call the base
method without any aspects? I thought that every pre and post thingy
should be forced to work with the other, am I wrong?

because it will cause a endless loop..

if the current method is named 'foo', within this method i apply a advice,
to which i pass the current object itself.. and within the advice i again
call the foo method of the object... bang! loop..

however i wonder if this is just a normal thing and should be taken
care of by the user itself..