Class: FlatFile

Inherits:
Object show all
Defined in:
lib/flat_file.rb

Defined Under Namespace

Classes: FieldDef, FlatFileException, LongRecordError, Record, RecordLengthError, ShortRecordError

Constant Summary collapse

@@subclass_data =

A hash of data stored on behalf of subclasses. One hash key for each subclass.

Hash.new(nil)
@@unique_id =

Used to generate unique names for pad fields which use :auto_name.

0

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.add_field(name = nil, options = {}) {|fd| ... } ⇒ Object

Add a field to the FlatFile subclass. Options can include

:width - number of characters in field (default 10) :filter - callack, lambda or code block for processing during reading :formatter - callback, lambda, or code block for processing during writing

class SomeFile < FlatFile
  add_field :some_field_name, :width => 35
end

Yields:

  • (fd)


401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
# File 'lib/flat_file.rb', line 401

def self.add_field(name=nil, options={},&block)
    options[:width] ||= 10;

    fields      = get_subclass_variable 'fields'
    width       = get_subclass_variable 'width'
    pack_format = get_subclass_variable 'pack_format'
    
   
    fd = FieldDef.new(name,options,self)
   yield(fd) if block_given?

    fields << fd
    width += fd.width
    pack_format << "A#{fd.width}"
    set_subclass_variable 'width', width
    fd
end

.fieldsObject



468
469
470
# File 'lib/flat_file.rb', line 468

def self.fields
    self.get_subclass_variable 'fields'
end

.has_field?(field_name) ⇒ Boolean

Returns:

  • (Boolean)


472
473
474
475
476
477
478
479
# File 'lib/flat_file.rb', line 472

def self.has_field?(field_name)
  
  if self.fields.select { |f| f.name == field_name.to_sym }.length > 0
    true
  else
    false
  end
end

.new_pad_nameObject

:nodoc:



429
430
431
# File 'lib/flat_file.rb', line 429

def self.new_pad_name #:nodoc:
    "pad_#{ @@unique_id+=1 }".to_sym
end

.new_record(model = nil, &block) ⇒ Object

Create a new empty record object conforming to this file.



437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
# File 'lib/flat_file.rb', line 437

def self.new_record(model = nil, &block)
    fields = get_subclass_variable 'fields'

 record = Record.new(self)
 
 fields.map do |f| 
       assign_method = "#{f.name}="
    value = model.respond_to?(f.name.to_sym) ? model.send(f.name.to_sym) : ""
    record.send(assign_method, value)
    end

 if block_given?
     yield block, record
    end

 record
end

.non_pad_fieldsObject



460
461
462
# File 'lib/flat_file.rb', line 460

def self.non_pad_fields
    self.fields.select { |f| not f.is_padding? }
end

.pack_formatObject



496
497
498
# File 'lib/flat_file.rb', line 496

def self.pack_format
    get_subclass_variable 'pack_format'
end

.pad(name, options = {}) ⇒ Object

Add a pad field. To have the name auto generated, use :auto_name for the name parameter. For options see add_field.



421
422
423
424
425
426
427
# File 'lib/flat_file.rb', line 421

def self.pad(name, options = {})
    fd = self.add_field(
        name.eql?(:auto_name) ? self.new_pad_name : name,
        options
    )
    fd.padding = true
end

.widthObject



481
482
483
# File 'lib/flat_file.rb', line 481

def self.width
    get_subclass_variable 'width'
end

Instance Method Details

#create_record(line, line_number = -1)) ⇒ Object

create a record from line. The line is one line (or record) read from the text file. The resulting record is an object which. The object takes signals for each field according to the various fields defined with add_field or varients of it.

line_number is an optional line number of the line in a file of records. If line is not in a series of records (lines), omit and it’ll be -1 in the resulting record objects. Just make sure you realize this when reporting errors.

Both a getter (field_name), and setter (field_name=) are available to the user.



376
377
378
379
380
381
382
383
384
385
386
387
388
389
# File 'lib/flat_file.rb', line 376

def create_record(line, line_number = -1) #:nodoc:
    h = Hash.new 

    pack_format = self.class.get_subclass_variable 'pack_format'
    fields      = self.class.get_subclass_variable 'fields'
    
    f = line.unpack(pack_format)
    (0..(fields.size-1)).map do |index|
        unless fields[index].is_padding?
            h.store fields[index].name, fields[index].pass_through_filters(f[index])
        end
    end
    Record.new(self.class, h, line_number)
end

#each_record(io, &block) ⇒ Object

Iterate through each record (each line of the data file). The passed block is passed a new Record representing the line.

s = SomeFile.new
s.each_record(open('/path/to/file')) do |r|
  puts r.first_name
end


350
351
352
353
354
355
356
357
358
359
360
361
362
# File 'lib/flat_file.rb', line 350

def each_record(io,&block)
    io.each_line do |line|
        required_line_length = self.class.get_subclass_variable 'width'
        #line = io.readline
        line.chop!
        next if line.length == 0
        difference = required_line_length - line.length
        raise RecordLengthError.new(
            "length is #{line.length} but should be #{required_line_length}"
        ) unless(difference == 0)
        yield(create_record(line, io.lineno), line)
    end
end

#fieldsObject

Return a lsit of fields for the FlatFile subclass



456
457
458
# File 'lib/flat_file.rb', line 456

def fields 
    self.class.fields
end

#next_record(io, &block) ⇒ Object

Raises:



324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
# File 'lib/flat_file.rb', line 324

def next_record(io,&block) 
    return nil if io.eof?
    required_line_length = self.class.get_subclass_variable 'width'
    line = io.readline
    line.chop!
    return nil if line.length == 0
    difference = required_line_length - line.length
    raise RecordLengthError.new(
       "length is #{line.length} but should be #{required_line_length}"
    ) unless(difference == 0)

    if block_given?
        yield(create_record(line, io.lineno), line)
    else
        create_record(line,io.lineno)
    end
end

#non_pad_fieldsObject



464
465
466
# File 'lib/flat_file.rb', line 464

def non_pad_fields
  self.non_pad_fields
end

#pack_formatObject

Returns the pack format which is generated from add_field calls. This format is used to unpack each line and create Records.



492
493
494
# File 'lib/flat_file.rb', line 492

def pack_format 
    self.class.get_pack_format
end

#widthObject

Return the record length for the FlatFile subclass



486
487
488
# File 'lib/flat_file.rb', line 486

def width 
    self.class.width
end