From: Michael Guterl Date: 2006-04-23T13:09:42+09:00 Subject: Re: Metaprogramming is fun! ------=_Part_31815_30029556.1145765378256 Content-Type: multipart/alternative; boundary="----=_Part_31816_14544355.1145765378256" ------=_Part_31816_14544355.1145765378256 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Content-Disposition: inline I forgot, here's the test data in case anyone wants it. Michael Guterl On 4/23/06, Michael Guterl wrote: > > I finally decided to dive in and give metaprogramming in Ruby a shot. I'= m > not sure that my example is exactly practical, but it seemed useful at th= e > time. There's a few areas I would like to hear others suggestions on: > > 1. Does the syntax appear to be in line with the community standards? > > 2. Are my uses of class_eval and instance_eval okay / is there a better > way? > > 3. I am using facets because I like the Dictionary (OrderedHash), but I'm > sure there are better ways to build the structure while preserving the fi= eld > order. I especially don't like the fact that I have to specify Dictionar= y[] > in the structure of the subclass. > > 4. Please comment on the code in general, I'm open to any kind of > criticism. > > I'm not sure if it's customary to attach the code in a file or post it in > the email. I apologize if I should have attached the code in a file. > > Michael Guterl > > ---------------------------------------------- > > require 'rubygems' > require 'facets' > require 'dictionary' > > class FixedLength > > def self.structure(ordered_hash) > > class_eval do > @@structure =3D ordered_hash > end > > keys =3D @@structure.keys > instance_eval do > attr_accessor *keys > end > > end > > # this entire method could probably be a lot cleaner > > def self.open(file_name) > class_eval do > data =3D IO.read(file_name) > records =3D [] > data.each_line do |line| > last_position =3D 0 > record =3D self.new > @@structure.each_pair do |name, length| > record.instance_variable_set( "@#{name.to_s}", line.slice(last_= position, > length.to_i).strip) > last_position +=3D length.to_i > end > records << record > end > return records > end > end > > end > > class InputStructure < FixedLength > > # I'd like to clean this up, either removing the need for Dictionary[] > and the separation by commas > # or with something like this > # column.add :id, 10 > # column.add :phone, 10 > # column.add :first_name, 25 > # etc. I'd love to hear some suggestions. > > structure Dictionary[ :id , 10, > :phone , 10, > :first_name , 25, :middle_name , 1, :last_name , 25, > :address , 30, > :city , 25, > :state , 2, > :zip , 5, :zip4 , 4 ] > > end > > require 'test/unit' > > class InputStructureTest < Test::Unit::TestCase > > def setup > @records =3D InputStructure.open('fixed_data.txt') > end > > def test_first > record =3D @records.first > assert_equal "1", record.id > assert_equal "1234567890", record.phone > assert_equal "SOME RANDOM", record.first_name > assert_equal "", record.middle_name > assert_equal "PERSON", record.last_name > assert_equal "1234 SOME RANDOM STREET", record.address > assert_equal "RANDOM CITY", record.city > assert_equal "OH", record.state > assert_equal "45219", record.zip > assert_equal "", record.zip4 > end > > end > > ------=_Part_31816_14544355.1145765378256 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Content-Disposition: inline I forgot, here's the test data in case anyone wants it.

Michael Gute= rl

On 4/23/06, Michael Guterl <mgute= rl@gmail.com > wrote:
I finally decided to dive in and give m= etaprogramming in Ruby a shot.  I'm not sure that my example is exactl= y practical, but it seemed useful at the time.  There's a few areas I = would like to hear others suggestions on:

1. Does the syntax appear to be in line with the community standards?
2. Are my uses of class_eval and instance_eval okay / is there a bett= er way?

3. I am using facets because I like the Dictionary (OrderedH= ash), but I'm sure there are better ways to build the structure while prese= rving the field order.  I especially don't like the fact that I have t= o specify Dictionary[] in the structure of the subclass.

4. Please comment on the code in general, I'm open to any kind of c= riticism.

I'm not sure if it's customary to attach the code in a fil= e or post it in the email.  I apologize if I should have attached the = code in a file.

Michael Guterl

---------------------------------------------= -

require 'rubygems'
require 'facets'
require 'dictionary'
=
class FixedLength

  def self.structure(ordered_hash)
&nb= sp;
    class_eval do
      @@struct= ure =3D ordered_hash
    end
 
  &n= bsp; keys =3D @@structure.keys
    instance_eval do
&n= bsp;     attr_accessor *keys
    end<= br>   
  end
 
  # this entire met= hod could probably be a lot cleaner

  def self.open(file_name)
    class_eval do=
      data =3D IO.read(file_name)
 &nb= sp;    records =3D []
      data= .each_line do |line|
        last_pos= ition =3D 0
        record =3D self.n= ew
        @@structure.each_pair do |name, length|
         = ; record.instance_variable_set( "@#{name.to_s}", line.slice(last_= position, length.to_i).strip)
       =    last_position +=3D length.to_i
    &nbs= p;   end
        records &l= t;< record
      end
      re= turn records
    end
  end

end

clas= s InputStructure < FixedLength

  # I'd like to clean this up= , either removing the need for Dictionary[] and the separation by commas
  # or with something like this
  # column.add :id, 10
=   # column.add :phone, 10
  # column.add :first_name, 25
&n= bsp; # etc.  I'd love to hear some suggestions.

  structur= e Dictionary[ :id , 10,
        = ;    :phone , 10,=20
            :fir= st_name , 25, :middle_name , 1, :last_name , 25,
   &nbs= p;        :address , 30,
  = ;          :city , 25,
&nb= sp;           :state , 2,=
            :zi= p , 5, :zip4 , 4 ]

end

require 'test/unit'

class InputStructureTest < Test::Unit::TestCase

  de= f setup
    @records =3D InputStructure.open('fixed_data.= txt')
  end
 
  def test_first
  &nbs= p; record =3D @records.first
    assert_equal "1&quo= t;,=20 record.id
    assert_equ= al "1234567890", record.phone
    assert_equal = "SOME RANDOM", record.first_name
    assert_equal "", record.middle_name
&nb= sp;   assert_equal "PERSON",=20 record.last_name
    assert_equal "1234 SOME RANDOM = STREET", record.address
    assert_equal "RANDO= M CITY", record.city
    assert_equal "OH"= , record.state
    assert_equal "45219",=20 record.zip
    assert_equal "", record.zip4
=   end
 
end


------=_Part_31816_14544355.1145765378256-- ------=_Part_31815_30029556.1145765378256 Content-Type: text/plain; name=fixed_data.txt; charset=us-ascii Content-Transfer-Encoding: 7bit X-Attachment-Id: f_emcv3dvs Content-Disposition: attachment; filename="fixed_data.txt" 1 1234567890SOME RANDOM PERSON 1234 SOME RANDOM STREET RANDOM CITY OH45219 ------=_Part_31815_30029556.1145765378256--