Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Automagic class prototyping

Reply
Thread Tools

Automagic class prototyping

 
 
Aleks Kissinger
Guest
Posts: n/a
 
      07-25-2006
Anybody know any slick techniques for automatically prototyping
classes so they can interact with each other in top-level code? I've
run through two methods, but I'm not real wild about either of them.

Say for example, classes represent some security label and I want to
allow things with one label to access those of another label. So,
these hypothetical classes all descent from Sec....

class Sec
class <<self
def allow(c)
(@allowed_classes||=[]) <<c
end
end
end


And I want to ultimately just indescriminately run stuff like this:

class Documents < Sec
allow Downloads
end

class Downloads < Sec
allow Documents
end

But this is a run-time error unless the classes are prototyped somehow. Like:

class Downloads < Sec; end

class Documents < Sec
allow Downloads
end

class Downloads < Sec
allow Documents
end

As a framework, this would be so much nicer for the end-user if it
does that automatically, so she doesnt have to thing about declaration
order. So thats the problem. Possible solutions I've tried:

1. Grep-prototyping:
File.grep out all class defs and eval them before I actually require
the code. I don't like this because it chokes on classes defined
inside of modules or other classes. Grep has no idea about the
structure of the ruby code.

2. Delayed execution of the 'allow' statements.
I dump allow statements off into proc's then after all the definitions
are loaded, I run them. This works great, but syntactically its
clunky.

class Documents < Sec
later do
allow Downloads
end
end

class Downloads < Sec
later do
allow Documents
end
end

with:
class Sec
class << self
def later(&code)
(@code_for_later||=[]) << code
end
end

And I go back and exec all the @code_for_later blocks when all the
files are require'd. So, if any of you have questions about this code
or have any ideas for a prettier way to do it, I'd love to hear it.

 
Reply With Quote
 
 
 
 
Alex Young
Guest
Posts: n/a
 
      07-25-2006
Aleks Kissinger wrote:
> Anybody know any slick techniques for automatically prototyping
> classes so they can interact with each other in top-level code? I've
> run through two methods, but I'm not real wild about either of them.
>
> Say for example, classes represent some security label and I want to
> allow things with one label to access those of another label. So,
> these hypothetical classes all descent from Sec....
>
> class Sec
> class <<self
> def allow(c)
> (@allowed_classes||=[]) <<c
> end
> end
> end
>
>
> And I want to ultimately just indescriminately run stuff like this:
>
> class Documents < Sec
> allow Downloads
> end
>
> class Downloads < Sec
> allow Documents
> end
>
> But this is a run-time error unless the classes are prototyped somehow.
> Like:
>
> class Downloads < Sec; end
>
> class Documents < Sec
> allow Downloads
> end
>
> class Downloads < Sec
> allow Documents
> end
>
> As a framework, this would be so much nicer for the end-user if it
> does that automatically, so she doesnt have to thing about declaration
> order. So thats the problem. Possible solutions I've tried:
>
> 1. Grep-prototyping:
> File.grep out all class defs and eval them before I actually require
> the code. I don't like this because it chokes on classes defined
> inside of modules or other classes. Grep has no idea about the
> structure of the ruby code.
>
> 2. Delayed execution of the 'allow' statements.
> I dump allow statements off into proc's then after all the definitions
> are loaded, I run them. This works great, but syntactically its
> clunky.


3:
class Sec
class <<self
def allow(c)
begin
Kernel.const_get(c)
rescue NameError #is there a better way to do this?
class c < Sec; end
end
(@allowed_classes||=[]) <<c
end
end
end

There's probably stuff in there to trip you up, but you get the idea.
I'm not too keen on using an exception like that, but I can't seem to
find a better or more succinct way to test for the existence of a class.

--
Alex


 
Reply With Quote
 
 
 
 
Caleb Clausen
Guest
Posts: n/a
 
      07-26-2006
If you merge the functions of your #later and #allow, you could write
something like this:

class Documents < Sec
allow{Downloads}
end

class Downloads <Sec
allow{Documents}
end

 
Reply With Quote
 
Aleks Kissinger
Guest
Posts: n/a
 
      07-26-2006
Thanks for the suggestions. The problem with the rescue on NameError
technique is the exception gets thrown before we're actually in the
method body of allow, since the offender is a parameter. I dig the
idea of combining allow and later, but it gets a little uglier since I
really need allow to take multiple args...

allow {[ClassA, ClassB, OpC]}

However, thats nicer looking than some of the other alternatives. If
there was some sort of hook or metaprogramming magic that would delay
executing class bodies until everything was defined, that would be
ideal, but that might be stretching a little too far.

 
Reply With Quote
 
ara.t.howard@noaa.gov
Guest
Posts: n/a
 
      07-26-2006
On Wed, 26 Jul 2006, Aleks Kissinger wrote:

> Anybody know any slick techniques for automatically prototyping
> classes so they can interact with each other in top-level code? I've
> run through two methods, but I'm not real wild about either of them.
>
> Say for example, classes represent some security label and I want to
> allow things with one label to access those of another label. So,
> these hypothetical classes all descent from Sec....
>
> class Sec
> class <<self
> def allow(c)
> (@allowed_classes||=[]) <<c
> end
> end
> end
>
>
> And I want to ultimately just indescriminately run stuff like this:
>
> class Documents < Sec
> allow Downloads
> end
>
> class Downloads < Sec
> allow Documents
> end
>
> But this is a run-time error unless the classes are prototyped somehow.
> Like:
>
> class Downloads < Sec; end
>
> class Documents < Sec
> allow Downloads
> end
>
> class Downloads < Sec
> allow Documents
> end
>
> As a framework, this would be so much nicer for the end-user if it
> does that automatically, so she doesnt have to thing about declaration
> order. So thats the problem. Possible solutions I've tried:



harp:~ > cat a.rb
class Sec
ALLOWED_CLASSES = []

def self.allowed_classes
ALLOWED_CLASSES
end

def self.allow *list
allowed_classes.push *list
allowed_classes.uniq!
allowed_classes
end

def self.const_missing c
c
end

def self.allowed
allowed_classes.map{|c| eval c.to_s }
end
end

class Documents < Sec
allow Downloads
end

class Foobar < Sec
allow Downloads
end

class Downloads < Sec
allow Documents, Foobar
end

p Sec.allowed



harp:~ > ruby a.rb
[Downloads, Documents, Foobar]


i'd push/pop that 'const_missing' handler during the 'allow' method to avoid
any nasty recursion. but there ya go.

-a
--
suffering increases your inner strength. also, the wishing for suffering
makes the suffering disappear.
- h.h. the 14th dali lama

 
Reply With Quote
 
Aleks Kissinger
Guest
Posts: n/a
 
      07-26-2006
I can see some pitfalls here, but this is the most promising technique
I've seen so far.

On 7/26/06, http://www.velocityreviews.com/forums/(E-Mail Removed) <(E-Mail Removed)> wrote:
> On Wed, 26 Jul 2006, Aleks Kissinger wrote:
>
> > Anybody know any slick techniques for automatically prototyping
> > classes so they can interact with each other in top-level code? I've
> > run through two methods, but I'm not real wild about either of them.
> >
> > Say for example, classes represent some security label and I want to
> > allow things with one label to access those of another label. So,
> > these hypothetical classes all descent from Sec....
> >
> > class Sec
> > class <<self
> > def allow(c)
> > (@allowed_classes||=[]) <<c
> > end
> > end
> > end
> >
> >
> > And I want to ultimately just indescriminately run stuff like this:
> >
> > class Documents < Sec
> > allow Downloads
> > end
> >
> > class Downloads < Sec
> > allow Documents
> > end
> >
> > But this is a run-time error unless the classes are prototyped somehow.
> > Like:
> >
> > class Downloads < Sec; end
> >
> > class Documents < Sec
> > allow Downloads
> > end
> >
> > class Downloads < Sec
> > allow Documents
> > end
> >
> > As a framework, this would be so much nicer for the end-user if it
> > does that automatically, so she doesnt have to thing about declaration
> > order. So thats the problem. Possible solutions I've tried:

>
>
> harp:~ > cat a.rb
> class Sec
> ALLOWED_CLASSES = []
>
> def self.allowed_classes
> ALLOWED_CLASSES
> end
>
> def self.allow *list
> allowed_classes.push *list
> allowed_classes.uniq!
> allowed_classes
> end
>
> def self.const_missing c
> c
> end
>
> def self.allowed
> allowed_classes.map{|c| eval c.to_s }
> end
> end
>
> class Documents < Sec
> allow Downloads
> end
>
> class Foobar < Sec
> allow Downloads
> end
>
> class Downloads < Sec
> allow Documents, Foobar
> end
>
> p Sec.allowed
>
>
>
> harp:~ > ruby a.rb
> [Downloads, Documents, Foobar]
>
>
> i'd push/pop that 'const_missing' handler during the 'allow' method to avoid
> any nasty recursion. but there ya go.
>
> -a
> --
> suffering increases your inner strength. also, the wishing for suffering
> makes the suffering disappear.
> - h.h. the 14th dali lama
>
>


 
Reply With Quote
 
Logan Capaldo
Guest
Posts: n/a
 
      07-26-2006

On Jul 26, 2006, at 1:40 AM, Aleks Kissinger wrote:

> Thanks for the suggestions. The problem with the rescue on NameError
> technique is the exception gets thrown before we're actually in the
> method body of allow, since the offender is a parameter. I dig the
> idea of combining allow and later, but it gets a little uglier since I
> really need allow to take multiple args...
>
> allow {[ClassA, ClassB, OpC]}
>
> However, thats nicer looking than some of the other alternatives. If
> there was some sort of hook or metaprogramming magic that would delay
> executing class bodies until everything was defined, that would be
> ideal, but that might be stretching a little too far.
>


how about:

class Sec
def self.const_missing(constant_name)
Object.const_set(constant_name, Class.new(Sec))
end
end





 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
[ANN] rcodetools 0.5.0 (TDD++, automagic assertions, 100% accurate completion, doc/code browsing...) Mauricio Fernandez Ruby 4 02-08-2007 10:27 AM
[ANN] rcodetools 0.4.1 (TDD++, automagic assertions, accurate completion, doc/code browsing...) Mauricio Fernandez Ruby 2 01-14-2007 05:23 PM
[ANN] rcodetools 0.4.0: TDD++, automagic assertions, 100% accurate completion, doc/code browsing... Mauricio Fernandez Ruby 4 12-30-2006 07:19 PM
[ANN] xmpfilter 0.3.0: automagic Test::Unit assertions and RSpec expectations Mauricio Fernandez Ruby 1 10-16-2006 10:22 AM
Automagic determination of definition based on definition location. Jon Slaughter C++ 4 10-26-2005 05:00 PM



Advertisments