"attr" like functions

B

Ben Giddings

I came across an interesting problem today. Say you wanted to have an
object where all the instance variables have an associated description.
You also wanted to have a 'pretty_print' method, that would print out
the description of the variable, along with the value. Here's how the
ideal code would look:

class Coordinate < DescribedObject
attr_with_desc :x, "X Coordinate"
attr_with_desc :y, "Y Coordinate"
attr_with_desc :z, "Z Coordinate"
end

coord = Coordinate.new
coord.x = 1
coord.y = 2
coord.z = 3

coord.pretty_print
X Coordinate: 1
Y Coordinate: 2
Z Coordinate: 3


I managed to get that kind of behaviour with this code:


class Module
def attr_with_desc(sym, desc="Instance var")
attr_accessor sym
eval_str = "@@desc[\"@#{sym.id2name}\"] = \"#{desc.to_s}\""
puts(eval_str)
module_eval(eval_str)
end
end

class DescribedObject
@@desc = Hash.new

def pretty_print
instance_variables.each {
|var|
if @@desc.has_key?(var)
puts "#{@@desc[var]}: #{eval(var)}"
else
puts "Instance var #{var}: #{eval(var)}"
end
}
end
end

class Coordinate < DescribedObject
attr_with_desc :x, "X Coord"
attr_with_desc :y, "Y Coord"
attr_with_desc :z, "Z Coord"
end


But there are still a couple of things that I don't think are ideal
about this, and wonder if it is possible to fix:

1) Is there a way to add the 'attr_with_desc' method without having to
modify the Module class? I'd like to keep it pristine, if possible.

2) Both Module and DescribedObject have to know that the variable is
named '@@desc', so if they get out of sync, then that could be bad. Is
there a way of grouping all the code into one class/module?

Ben
 
L

leon breedt

1) Is there a way to add the 'attr_with_desc' method without having to
modify the Module class? I'd like to keep it pristine, if possible.
not sure why you're putting a class method in Module, putting it in
the class itself would suffice?

--<snip>--

class Describable
def Describable.attr_with_desc(id, description)
attr_accessor id
@@desc ||= {}
@@desc["@#{id.id2name}"] = description.to_s
end
def pretty_print
instance_variables.each { |var|
if @@desc.has_key?(var)
puts "#{@@desc[var]}: #{eval(var)}"
else
puts "Instance var #{var}: #{eval(var)}"
end
}
end
end

class Test<Describable
attr_with_desc :name, "Name of the test"
attr_with_desc :version, "Version of the test"
end

t = Test.new
t.name = "test"
t.version = 1.0
t.pretty_print

--<snip>--

regards,
leon
 
L

Lennon Day-Reynolds

Perhaps making Describable a module, rather than class, would be more
appropriate here. If nothing else, the 'attr_with_desc' method should
be available in objects that subclass a different type than
Describable.

Lennon
 

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

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top