Extensible meta-data?


(Its Me) #1

I need to easily attach various kinds of meta-data to modules, classes,
methods, constants, instance variables, etc. I would like to be able to
write things that are, broadly, like this:

class C
def M

end meta { keyA => objA, keyB => objB }

end meta { key1 => obj1, key2 => obj2 }

I will typically use this to distinguish different kinds of classes,
methods, etc in my own ontology, to do some Ruby code generation into the
corresponding class, method, etc, and to reverse that code generation if
needed when the meta-data is changed.

This is also the reason I eas expecting that class …end would return the
class, def … end should return the unbound method (or something close to
these) in a uniform POLS manner.

This kind of need has probably arisen before. Is there some recommended way,
idiom, or (ideally) code to do this?

Will Ruby 2.0 have any direct support for such extensible meta-data?

Thanks …


(Laurent Julliard) #2

look on RAA for ‘metatags’

···

il Thu, 26 Feb 2004 17:52:35 GMT, “Its Me” itsme213@hotmail.com ha scritto::

I need to easily attach various kinds of meta-data to modules, classes,
methods, constants, instance variables, etc. I would like to be able to
write things that are, broadly, like this:


(Its Me) #3

Thanks, but this is very oriented towards documentation strings. I am
looking for something that operates at the meta-level, adding and removing
interlinked structures to classes, methods, … This is roughly the change
from Javadoc tags to Java 1.5’s metadata annotations (or, equivalently, to
C# metadata attributes).

My very preliminary thoughts are along these lines:
module Meta
# meta allows adding and removing arbitrary properties
def meta … end
end

class Method # perhaps I need to use UnboundMethod?
include Meta
end

class Parameter # I would like this but it seems impossible to hook into
include Meta
end

class Attribute

one instance of this for each attribute

Ruby does not have such a class, so I would build my own versions of

attr: or attr_accessor:
include Meta
end

class Class
include Meta
end

And then use this:
class Mine; end meta … # metadata on Mine

class Mine
def foo; end meta … # metadata on Mine#foo
end

Thoughts? Am I trying to do something ridiculous?

···

“gabriele renzi” surrender_it@remove.yahoo.it wrote

look on RAA for ‘metatags’


(Robert) #4

“Its Me” itsme213@hotmail.com schrieb im Newsbeitrag
news:x8s%b.4637$OH4.695@fe2.texas.rr.com…

look on RAA for ‘metatags’

Thanks, but this is very oriented towards documentation strings. I am
looking for something that operates at the meta-level, adding and
removing
interlinked structures to classes, methods, … This is roughly the
change
from Javadoc tags to Java 1.5’s metadata annotations (or, equivalently,
to
C# metadata attributes).

My very preliminary thoughts are along these lines:
module Meta
# meta allows adding and removing arbitrary properties
def meta … end
end

class Method # perhaps I need to use UnboundMethod?
include Meta
end

class Parameter # I would like this but it seems impossible to hook into
include Meta
end

class Attribute

one instance of this for each attribute

Ruby does not have such a class, so I would build my own versions of

attr: or attr_accessor:
include Meta
end

class Class
include Meta
end

And then use this:
class Mine; end meta … # metadata on Mine

I don’t think this will work since class…end doesn’t return the class.

class Mine
def foo; end meta … # metadata on Mine#foo
end

Thoughts? Am I trying to do something ridiculous?

How about this:

class Module
def meta(*args)
case args.size
when 0
meta_data[self]
when 1
if args[0].kind_of? Hash
meta_data[self].update args[0]
else
meta_data[args[0]]
end
when 2
meta_data[args[0]].update args[1]
else
raise ArgumentError, "Wrong number of args"
end
end

def meta_data
@meta ||= Hash.new {|h,k| h[k] = {}}
end
end

class Foo
def foo; puts “bar”; end
meta :foo, “method” => “metadata”, “foo” => "bar"
meta “class” => “metadata”, “foo” => "bar"
end

p Foo.meta :foo
p Foo.meta

robert
···

“gabriele renzi” surrender_it@remove.yahoo.it wrote


(Its Me) #5

“Robert Klemme” bob.news@gmx.net wrote…

And then use this:
class Mine; end meta … # metadata on Mine

I don’t think this will work since class…end doesn’t return the class.

Correct. I know I could stick in a “self” before the end to make it work,
but am very curious why it does not return the class. Similarly, I am very
curious why def…end does not return a useful object (UnboundMethod? Proc?
I’m not a guru, but “nil” is not an intuitive return to me).

class Mine
def foo; end meta … # metadata on Mine#foo
end

Thoughts? Am I trying to do something ridiculous?

How about this:

class Module
def meta(*args)
case args.size
when 0
meta_data[self]
when 1
if args[0].kind_of? Hash
meta_data[self].update args[0]
else
meta_data[args[0]]
end
when 2
meta_data[args[0]].update args[1]
else
raise ArgumentError, "Wrong number of args"
end
end

def meta_data
@meta ||= Hash.new {|h,k| h[k] = {}}
end
end

class Foo
def foo; puts “bar”; end
meta :foo, “method” => “metadata”, “foo” => "bar"
meta “class” => “metadata”, “foo” => "bar"
end

p Foo.meta :foo
p Foo.meta

I really want to attach Method meta-data to the Method, not to the class. If
I can’t figure out how to get a handle on the method object, then perhaps
I’ll do something like this.

Thanks for the code; always amazes me how others’ experience shows in much
more efficient coding styles than my own :slight_smile:


(Robert) #6

“Its Me” itsme213@hotmail.com schrieb im Newsbeitrag
news:l9L%b.8114$lS1.3171@fe2.texas.rr.com…

“Robert Klemme” bob.news@gmx.net wrote…

And then use this:
class Mine; end meta … # metadata on Mine

I don’t think this will work since class…end doesn’t return the class.

Correct. I know I could stick in a “self” before the end to make it work,
but am very curious why it does not return the class. Similarly, I am very
curious why def…end does not return a useful object (UnboundMethod?
Proc?
I’m not a guru, but “nil” is not an intuitive return to me).

class Mine
def foo; end meta … # metadata on Mine#foo
end

Thoughts? Am I trying to do something ridiculous?

How about this:

class Module
def meta(*args)
case args.size
when 0
meta_data[self]
when 1
if args[0].kind_of? Hash

Even nicer:
if Hash === args[0]

      meta_data[self].update args[0]
    else
      meta_data[args[0]]
    end
  when 2
    meta_data[args[0]].update args[1]
  else
    raise ArgumentError, "Wrong number of args"
end

end

def meta_data
@meta ||= Hash.new {|h,k| h[k] = {}}
end
end

class Foo
def foo; puts “bar”; end
meta :foo, “method” => “metadata”, “foo” => "bar"
meta “class” => “metadata”, “foo” => "bar"
end

p Foo.meta :foo
p Foo.meta

I really want to attach Method meta-data to the Method, not to the class.
If
I can’t figure out how to get a handle on the method object, then perhaps
I’ll do something like this.

I tried a bit with instance_method but didn’t get the desired results so I
omitted that part. Now I know what’s wrong here: You can’t use
UnboundMethod as hash key because the hash value is not dependent on the
class and method identifier but on the id of the UnboundMethod object only:

irb(main):001:0> class Foo; def bar;end; end
=> nil
irb(main):002:0> Foo.instance_method( :bar )
=> #<UnboundMethod: Foo#bar>
irb(main):003:0> a = Foo.instance_method( :bar )
=> #<UnboundMethod: Foo#bar>
irb(main):004:0> b = Foo.instance_method( :bar )
=> #<UnboundMethod: Foo#bar>
irb(main):005:0> a == b
=> true
irb(main):006:0> b == a
=> true
irb(main):007:0> a.hash == b.hash
=> false
irb(main):008:0> a.id
=> 135052720
irb(main):009:0> a.hash
=> 135052720
irb(main):010:0> b.id
=> 135044800
irb(main):011:0> b.hash
=> 135044800

UnboundMethod#hash is broken in
$ ruby --version
ruby 1.8.1 (2003-12-25) [i386-cygwin]

Thanks for the code; always amazes me how others’ experience shows in much
more efficient coding styles than my own :slight_smile:

Thanks! It’s always fun to see what differnt solutions are possible with
Ruby.

Kind regards

robert