DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world
Ruby DBF Library Fixes
A handful of fixes/enhancements for the "dbf" Rubygem.
# 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





