Cut AOP implementation in Ruby

B

Brian Takita

------=_Part_11129_10061077.1137704723959
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Hello,

Does anybody know of a Cut-based
AOP<http://www.rubygarden.org/ruby?AspectOrientedRuby>library
implemented in ruby?
I found a c-based implementation in the
Suby<http://rubyforge.org/projects/suby/>project, but I don't know if
I want to open that can of
worms.<http://www.rubygarden.org/ruby?AspectOrientedRuby>

--
Thank you,
Brian Takita
http://weblog.freeopinion.org

------=_Part_11129_10061077.1137704723959--
 
T

Trans

A pure Ruby implementation is unfortuately far from ideal. Nonetheless
their are some appraoches that get close. Below I give one that I
developed awhile back. Also I believe Mauricio Fernandez has done some
expirementation on this too. Perhaps he has some ideas.

---- cut.rb ----

# Cut, Transparent Subclass
# Copyright (c) 2004 Thomas Sawyer
# cut.rb
#
# == Notes
#
# This implementation uses a single transparent subclass, the
ProxyCut,
# into which module mixins are included. This essentially works
# and allows cuts to be somewhat dynamic. But it does not follow the
# formal design of cuts which uses multiple transparent subclasses,
# not mixins.
#
# This implementation suffers from the dynamic module inclusion
problem.
# Due to the nature of module inclusion this is a somewhat serious
# limitation. The upshot of this is that cuts can only be defined on
# a class up to the point of instantiation. Adding subsequent cuts
# will not effect already instantiated objects. Thus all cuts to be
used
# must be defined before instantiation.

#
# = Class
#
class Class

alias_method :anew, :new

def new(*args, &blk)
proxycut.anew(*args, &blk)
end

def proxycut
@proxycut ||= ProxyCut.new(self)
end

private :proxycut

def cuts
proxycut.ancestors.select{ |a| a.is_a?(Cut) }
end

def preclude( mod )
proxycut.class_eval { include mod }
end

# this finds the nearest cut which lacks a specified method
def clearcut(meth)
#acuts = cut.ancestors.select{ |a| a.is_a?(Cut) }
r = cuts.reverse.detect{|a| !
a.instance_methods.include?(meth.to_s) }
return r
end

def wrap( meth, &meth_proc )
c = clearcut( meth )
c = Cut.new( self ) if ! c
c.send( :define_method, meth, &meth_proc )
return c
end

end


#
# = ProxyCut
#
class ProxyCut

def self.new(supclass)
Class.anew(supclass) #do
# this seems to cause problems
#alias_method :real_class, :class
#define_method:)class) { supclass }
#end
end

end


#
# = Cut
#
class Cut < Module

attr :superclass

def initialize(superclass, &block)
class_eval(&block) if block_given?
@superclass = superclass
s = self
@superclass.send:)proxycut).class_eval{ include s }
end

end


#
# = Kernel
#
module Kernel

def cut(cut_name, klass, &block)
self.class.module_eval { const_set( cut_name, Cut.new(klass,
&block) ) }
end

end



# ---- primative test ----

if __FILE__ == $0

class C
def m1; "X"; end
end

# cut A < C
A = Cut.new(C) do
def m1; "<" + super + ">"; end
end

# cut B < C
# cut B,C do
B = Cut.new(C) do
def m1; "[" + super + "]"; end
end

c = C.new

puts c.m1

p C.clearcut:)t)

p c.class

end
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top