Ruby DBF Library Fixes
# example.rb require 'rubygems' require 'dbf' require 'dbf_fixes' table = DBF::Table.new('/path/to/table.dbf', :in_memory => false) table.each_record do |record| # do something here # with in_memory=>false tables, each_record is much more efficient # because it reads directly from disk end
# dbf_fixes.rb module DBF class Record private # fix bug in DBF code (or workaround bug in FoxPro dbf files; I don't know :-) def initialize_values(columns) columns.each do |column| case column.type when 'I' # added by Tim - I don't understand this much, but it seems to work @attributes[column.name] = @data.read(column.length).unpack("I").first when 'N' # number @attributes[column.name] = column.decimal.zero? ? unpack_string(column).to_i : unpack_string(column).to_f when 'D' # date raw = unpack_string(column).strip unless raw.empty? begin parts = raw.match(DATE_REGEXP).to_a.slice(1,3).map {|n| n.to_i} @attributes[column.name] = Time.gm(*parts) rescue parts = raw.match(DATE_REGEXP).to_a.slice(1,3).map {|n| n.to_i} @attributes[column.name] = Date.new(*parts) end end when 'M' # memo starting_block = unpack_string(column).to_i @attributes[column.name] = read_memo(starting_block) when 'L' # logical @attributes[column.name] = unpack_string(column) =~ /^(y|t)$/i ? true : false else @attributes[column.name] = unpack_string(column).strip end end end # don't know why, but accessors stopped working for me. def define_accessors @table.columns.each do |column| underscored_column_name = underscore(column.name) if @table.options[:accessors] self.class.send :define_method, underscored_column_name do @attributes[column.name] end @@accessors_defined = true end end end end class Table # more efficient iterator (so we don't load everything) def each_record if options[:in_memory] and @records @records.each { |r| yield(r) } else 0.upto(@record_count - 1) do |n| seek_to_record(n) yield(DBF::Record.new(self)) unless deleted_record? end end end end end