Whats the ruby way of associating metadata with a function

Hi All,

I’ve pretty new to ruby and still getting to know how ruby works. I want
to associate some metadata to a function. I saw a similar post down this
line but didn’t get the real answer.

In javascript I’m used to associating metadata with a function as
follows.

foo.bar = “foobar”;
function foo(){
}

Whats the normal ruby practice to do this kind of a thing. Whats the
ruby way of doing this.

Your help is very much appreciated.

Thanks,
Keith.

2007/11/13, Keith C. [email protected]:

function foo(){
}

Whats the normal ruby practice to do this kind of a thing. Whats the
ruby way of doing this.

You typically use a class instance variable. For example:

class Foo
def self.meta() @method_meta ||= {} end

def bar() 1 end

meta[:bar]=567
puts meta[:bar], meta[:foo]
end

puts Foo.meta[:bar], Foo.meta[:foo]

Kind regards

robert

Hi Robert,

If I extend my question a bit further

foo.bar = “bar”;
function foo(){
}

foobar.bar = “foobar”;
function foobar(){
}

How can I support something like this?

Thanks,
Keith.

Robert K. wrote:

2007/11/13, Keith C. [email protected]:

function foo(){
}

Whats the normal ruby practice to do this kind of a thing. Whats the
ruby way of doing this.

You typically use a class instance variable. For example:

class Foo
def self.meta() @method_meta ||= {} end

def bar() 1 end

meta[:bar]=567
puts meta[:bar], meta[:foo]
end

puts Foo.meta[:bar], Foo.meta[:foo]

Kind regards

robert

On Nov 13, 4:43 am, Keith C. [email protected] wrote:

How can I support something like this?

require ‘ostruct’

class FunctionWithMetaData < OpenStruct
def initialize(&block)
super
@func = block
end

def call(*args)
@func.call(*args)
end
end

foo = FunctionWithMetaData.new { |x|
x*10
}

foo.bar = “qux”
foo.baz = “bop”

puts foo.bar # => “qux”
puts foo.baz # => “bop”
puts foo.call(3) # => 30

fred = FunctionWithMetaData.new {
“fred function”
}

fred.arms = 2
fred.fingers = 10

puts fred.arms # => 2
puts fred.fingers # => 10
puts fred.call # => “fred function”

2007/11/13, Keith C. [email protected]:

}

How can I support something like this?

The example is kind of artificial. Can you disclose more detail on
what you are trying to achieve? There are millions of ways to answer
your question and meta data for methods might not even be the best
solution.

Kind regards

robert

On Nov 13, 3:43 am, Keith C. [email protected] wrote:

ruby way of doing this.
Three options come to mind:

==================================================
#1 : add accessors to the singleton of a lambda

foo = lambda {
puts “foo!!”
}

class << foo
attr_accessor :bar
end

foo.bar = “foobar”

foo.call # => “foo!!”
puts foo.bar # => “foobar”

==================================================
#2 : add a hash to the singleton of a lambda

foo = lambda {
puts “foo!!”
}

class << foo
def meta
@meta ||= Hash.new
end
end

foo.meta[:bar] = “foobar”

foo.call # => “foo!!”
puts foo.meta[:bar] # => “foobar”

==================================================
#3 : add a method to the singleton of an OpenStruct

require ‘ostruct’

foo = OpenStruct.new

class << foo
def call
puts “foo!!”
end
end

foo.bar = “foobar”

foo.call # => “foo!!”
puts foo.bar # => “foobar”

All other things being equal, I would be inclined toward #3.

Hi Robert and others,

We are trying to define a way of writing web services in ruby (Code
First approach). And we expect to keep it as simple as possible. In
order to do this we need to define some metadata that we can use to
generate a pleasant WSDL. This metadata may include things like
documentation and details about input and output Types. Note that ruby
is a Dynamic language whereas xml schema is not. And although a
parameter taken into a function could be of anyType in most cases it
operates on it assuming its of a certain type. And getting this
information into the WSDL matters in that case.

Assume that I have a function as follows,

def foo(bar, foobar)

end

I need to get the information on the types expected by this function
across to the WSDL. I basically need a way to say that bar is a String
and foobar is an integer. This is where the matadata that I’m talking
about comes into play.

It will be nice if the Ruby community can help us figure out a nice
rubish way of doing this. The most important thing is that I want this
all to fit in with ruby people so this should look rubish as much as
possible.

Once we get this done we have more cool stuff in mind…

Thanks,
Keith.

Robert K. wrote:

2007/11/13, Keith C. [email protected]:

}

How can I support something like this?

The example is kind of artificial. Can you disclose more detail on
what you are trying to achieve? There are millions of ways to answer
your question and meta data for methods might not even be the best
solution.

Kind regards

robert

2007/11/15, Keith C. [email protected]:

information into the WSDL matters in that case.
about comes into play.

It will be nice if the Ruby community can help us figure out a nice
rubish way of doing this. The most important thing is that I want this
all to fit in with ruby people so this should look rubish as much as
possible.

Well, then it sounds as if you need structured data for a method.
Extending my last proposed solution a bit you could do this:

16:08:14 /cygdrive/c$ cat meta.rb
require ‘ostruct’

class Foo
def self.meta()
@method_meta ||= Hash.new {|h,k| h[k]=OpenStruct.new}
end

def bar() 1 end

meta[:bar].length=567
meta[:bar].return_type=Integer
end

puts Foo.meta[:bar]
16:08:48 /cygdrive/c$ ruby meta.rb
#
16:08:50 /cygdrive/c$

Of course you can use a Hash instead of the OpenStruct - but that’s
probably rather a matter of taste. If you need automatic discovery of
meta data set I’d probably rather use a Hash - if you know which meta
data you expect I’d probably use an OpenStruct or a Struct.

Cheers

robert