From: Alex Fenton Date: 2006-07-24T08:40:10+09:00 Subject: Re: Metaprogramming problems Hi Leslie Viljoen wrote: > I am pretty new to metaprogramming, this is my first shot. I want to > be able to take some binary data, split it into parts based on a > template and make an object with those parts. > ... You can do the kind of thing you want using eval, but there's easier ways in Ruby. > #Apply the template to a (binary data) string, producing an object > def apply(className, string) > evalString = "class #{className}\n" > @map.each do |attribute| > evalString << "attr_accessor :#{attribute[0]}\n" > end > evalString << "end\n" << "o = #{className}.new" > eval(evalString) > if attribute[1] == "a*" > eval("o.#{attribute[0]} = > string[#{currentPos}..-1].unpack(\"#{attribute[1]}\")") > else > eval("o.#{attribute[0]} = string[#{currentPos}, > #{size}].unpack(\"#{attribute[1]}\")") > currentPos += size > end > end > > return eval("o") > end > These are some ways of doing the same thing using Ruby methods: # Create a new class, assign it to a variable. new_class = Class.new() # Add an attribute accessor to the class a based on the template new_class.class_eval { attr_accessor :unit_id } # Create an instance of the new class item = new_class.new # Assign a value based on the data in your binary format item.unit_id = 666 > 1. I use the final eval("o") to return my object from eval-world. How > do I get my class from there? I want the new class I make to be > persistent at the top level so that I can make several objects of that > class later. If you want to use the class again later, store a reference to it in a constant or an instance variable. @my_class = Class.new() MyClass = Class.new() > 2. Once the class is created, I want to be able to go back and parse > another binary string, producing further fields and add those to the > existing class. My object would need to have the initial accessors > plus the new ones, and the new variables must be set. You can add methods dynamically to your new class at any time, using class_eval as above, or other techniques. Another alternative might be to create subclasses. cheers alex