Christer Nilsson wrote:
> I'm trying to communicate with a bank. Banks are still using the punched 
> card layout in their files.
> 
> Example: 001234567800023420060909
> (account=12345678, amount=234 and day=20060909)

> I would like to define the class like this (compare attr)
> 
> class Trans < Record
>   field :account, 10
>   field :amount, 6
>   ...

You're on the right lines, but in your example you're working with instance methods when you  want to work with class methods. Define a 'field' *class* method in the Record class, which defines reader and writer *instance* methods. Something like below. 

Tip - don't use method_missing unless you really have to; there is often another way, e.g. define_method. Some well-known libraries do it but it really screws up debugging and reflection, and makes method dispatch even slower.

hth
alex

___

class Record
  class Field
    attr_accessor :name, :length, :position
    def initialize
      yield self
    end
  end

  def Record.field(field_name, field_length)
    @fields ||= []
    position = @fields.inject(0) { | sum, f | sum += f.length }
    @fields << Field.new do | f | 
      f.name, f.length, f.position = field_name, field_length, position
    end
    attr_reader field_name
    define_method("#{field_name}=") do | value |
      value = value.to_s.rjust(field_length, '0')
      instance_variable_set("@#{field_name}", value)
    end
  end

  def Record.fields
    @fields
  end

  def initialize(str)
    self.class.fields.each do | field |
      send("#{field.name}=",  str[field.position, field.length])
    end
  end

  def to_s
    self.class.fields.inject('') { | str, f | str << send(f.name) }
  end
end

class Transaction < Record
  field :account, 10
  field :amount, 6
  field :lastday, 8
end

trans = Transaction.new("001234567800023420060909")
puts trans # 001234567800023420060909
puts trans.amount.to_i # 234

trans.amount = 120
puts trans # 001234567800012020060909