Class: DBF::Table

Inherits:
Object
  • Object
show all
Includes:
Schema, Enumerable
Defined in:
lib/dbf/table.rb

Overview

DBF::Table is the primary interface to a single DBF file and provides methods for enumerating and searching the records.

Direct Known Subclasses

Database::Table

Constant Summary collapse

DBF_HEADER_SIZE =
32
VERSIONS =
{
  '02' => 'FoxBase',
  '03' => 'dBase III without memo file',
  '04' => 'dBase IV without memo file',
  '05' => 'dBase V without memo file',
  '07' => 'Visual Objects 1.x',
  '30' => 'Visual FoxPro',
  '31' => 'Visual FoxPro with AutoIncrement field',
  '43' => 'dBASE IV SQL table files, no memo',
  '63' => 'dBASE IV SQL system files, no memo',
  '7b' => 'dBase IV with memo file',
  '83' => 'dBase III with memo file',
  '87' => 'Visual Objects 1.x with memo file',
  '8b' => 'dBase IV with memo file',
  '8e' => 'dBase IV with SQL table',
  'cb' => 'dBASE IV SQL table files, with memo',
  'f5' => 'FoxPro with memo file',
  'fb' => 'FoxPro without memo file'
}
FOXPRO_VERSIONS =
{
  '30' => 'Visual FoxPro',
  '31' => 'Visual FoxPro with AutoIncrement field',
  'f5' => 'FoxPro with memo file',
  'fb' => 'FoxPro without memo file'
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Schema

#activerecord_schema, #json_schema, #schema, #sequel_schema

Constructor Details

#initialize(data, memo = nil, encoding = nil) ⇒ Table

Opens a DBF::Table Examples:

# working with a file stored on the filesystem
table = DBF::Table.new 'data.dbf'

# working with a misnamed memo file
table = DBF::Table.new 'data.dbf', 'memo.dbt'

# working with a dbf in memory
table = DBF::Table.new StringIO.new(dbf_data)

# working with a dbf and memo in memory
table = DBF::Table.new StringIO.new(dbf_data), StringIO.new(memo_data)

# working with a dbf overriding specified in the dbf encoding
table = DBF::Table.new 'data.dbf', nil, 'cp437'
table = DBF::Table.new 'data.dbf', 'memo.dbt', Encoding::US_ASCII

Parameters:

  • data (String, StringIO)

    Path to the dbf file or a StringIO object

  • memo (optional String, StringIO) (defaults to: nil)

    Path to the memo file or a StringIO object

  • encoding (optional String, Encoding) (defaults to: nil)

    Name of the encoding or an Encoding object



64
65
66
67
68
69
70
71
72
73
# File 'lib/dbf/table.rb', line 64

def initialize(data, memo = nil, encoding = nil)
  @data = open_data(data)
  @data.rewind
  @header = Header.new(@data.read DBF_HEADER_SIZE)
  @encoding = encoding || header.encoding
  @memo = open_memo(data, memo)
  yield self if block_given?
rescue Errno::ENOENT
  raise DBF::FileNotFoundError, "file not found: #{data}"
end

Instance Attribute Details

#encodingObject

Returns the value of attribute encoding.



41
42
43
# File 'lib/dbf/table.rb', line 41

def encoding
  @encoding
end

#headerObject (readonly)

Returns the value of attribute header.



40
41
42
# File 'lib/dbf/table.rb', line 40

def header
  @header
end

Instance Method Details

#closeTrueClass, FalseClass

Closes the table and memo file

Returns:

  • (TrueClass, FalseClass)


83
84
85
86
# File 'lib/dbf/table.rb', line 83

def close
  @data.close
  @memo && @memo.close
end

#closed?TrueClass, FalseClass

Returns:

  • (TrueClass, FalseClass)


89
90
91
92
93
94
95
# File 'lib/dbf/table.rb', line 89

def closed?
  if @memo
    @data.closed? && @memo.closed?
  else
    @data.closed?
  end
end

#column_namesString

Column names

Returns:

  • (String)


204
205
206
# File 'lib/dbf/table.rb', line 204

def column_names
  columns.map(&:name)
end

#columnsArray

All columns

Returns:

  • (Array)


197
198
199
# File 'lib/dbf/table.rb', line 197

def columns
  @columns ||= build_columns
end

#each {|nil, DBF::Record| ... } ⇒ Object

Calls block once for each record in the table. The record may be nil if the record has been marked as deleted.

Yields:



106
107
108
# File 'lib/dbf/table.rb', line 106

def each
  header.record_count.times { |i| yield record(i) }
end

#filenameObject

Returns String.

Returns:

  • String



98
99
100
# File 'lib/dbf/table.rb', line 98

def filename
  File.basename @data.path
end

#find(command, options = {}) {|optional, DBF::Record, NilClass| ... } ⇒ Object

Find records using a simple ActiveRecord-like syntax.

Examples:

table = DBF::Table.new 'mydata.dbf'

# Find record number 5
table.find(5)

# Find all records for Keith Morrison
table.find :all, first_name: "Keith", last_name: "Morrison"

# Find first record
table.find :first, first_name: "Keith"

The command may be a record index, :all, or :first. options is optional and, if specified, should be a hash where the keys correspond to column names in the database. The values will be matched exactly with the value in the database. If you specify more than one key, all values must match in order for the record to be returned. The equivalent SQL would be “WHERE key1 = ‘value1’ AND key2 = ‘value2’”.

Parameters:

  • command (Fixnum, Symbol)
  • options (optional, Hash) (defaults to: {})

    Hash of search parameters

Yields:



181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/dbf/table.rb', line 181

def find(command, options = {}, &block)
  case command
  when Fixnum
    record(command)
  when Array
    command.map { |i| record(i) }
  when :all
    find_all(options, &block)
  when :first
    find_first(options)
  end
end

#has_memo_file?TrueClass, FalseClass

Returns:

  • (TrueClass, FalseClass)


76
77
78
# File 'lib/dbf/table.rb', line 76

def has_memo_file?
  !!@memo
end

#record(index) ⇒ DBF::Record, NilClass Also known as: row

Retrieve a record by index number. The record will be nil if it has been deleted, but not yet pruned from the database.

Parameters:

  • index (Fixnum)

Returns:



116
117
118
119
120
# File 'lib/dbf/table.rb', line 116

def record(index)
  seek_to_record(index)
  return nil if deleted_record?
  DBF::Record.new(@data.read(header.record_length), columns, version, @memo)
end

#record_countFixnum

Total number of records

Returns:

  • (Fixnum)


134
135
136
# File 'lib/dbf/table.rb', line 134

def record_count
  @record_count ||= header.record_count
end

#to_csv(path = nil) ⇒ Object

Dumps all records to a CSV file. If no filename is given then CSV is output to STDOUT.

Parameters:

  • path (optional String) (defaults to: nil)

    Defaults to STDOUT



149
150
151
152
153
154
# File 'lib/dbf/table.rb', line 149

def to_csv(path = nil)
  out_io = path ? File.open(path, 'w') : $stdout
  csv = CSV.new(out_io, force_quotes: true)
  csv << column_names
  each { |record| csv << record.to_a }
end

#versionString

Internal dBase version number

Returns:

  • (String)


127
128
129
# File 'lib/dbf/table.rb', line 127

def version
  @version ||= header.version
end

#version_descriptionString

Human readable version description

Returns:

  • (String)


141
142
143
# File 'lib/dbf/table.rb', line 141

def version_description
  VERSIONS[version]
end