Class: DBF::Table

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
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

DBASE2_HEADER_SIZE =
8
DBASE3_HEADER_SIZE =
32
DBASE7_HEADER_SIZE =
68
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',
  '32' => 'Visual FoxPro with field type Varchar or Varbinary',
  '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',
  '8c' => 'dBase 7',
  '8e' => 'dBase IV with SQL table',
  'cb' => 'dBASE IV SQL table files, with memo',
  'f5' => 'FoxPro with memo file',
  'fb' => 'FoxPro without memo file'
}.freeze
FOXPRO_VERSIONS =
{
  '30' => 'Visual FoxPro',
  '31' => 'Visual FoxPro with AutoIncrement field',
  'f5' => 'FoxPro with memo file',
  'fb' => 'FoxPro without memo file'
}.freeze

Constants included from Schema

Schema::FORMATS, Schema::OTHER_DATA_TYPES

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Schema

#activerecord_schema, #activerecord_schema_definition, #json_schema, #number_data_type, #schema, #schema_data_type, #schema_name, #sequel_schema, #sequel_schema_definition, #string_data_format

Constructor Details

#initialize(data, memo = nil, encoding = nil) {|_self| ... } ⇒ 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)

    data Path to the dbf file or a StringIO object

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

    memo Path to the memo file or a StringIO object

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

    encoding Name of the encoding or an Encoding object

Yields:

  • (_self)

Yield Parameters:

  • _self (DBF::Table)

    the object that the method was called on



79
80
81
82
83
84
# File 'lib/dbf/table.rb', line 79

def initialize(data, memo = nil, encoding = nil)
  @data = open_data(data)
  @encoding = encoding || header.encoding || Encoding.default_external
  @memo = open_memo(data, memo)
  yield self if block_given?
end

Instance Attribute Details

#encodingObject

Returns the value of attribute encoding.



50
51
52
# File 'lib/dbf/table.rb', line 50

def encoding
  @encoding
end

#nameString

Returns:

  • (String)


176
177
178
# File 'lib/dbf/table.rb', line 176

def name
  @name ||= filename && File.basename(filename, '.*')
end

Instance Method Details

#closeTrueClass, FalseClass

Closes the table and memo file

Returns:

  • (TrueClass, FalseClass)


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

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

#closed?TrueClass, FalseClass

Returns:

  • (TrueClass, FalseClass)


95
96
97
98
99
100
101
# File 'lib/dbf/table.rb', line 95

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

#column_namesString

Column names

Returns:

  • (String)


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

def column_names
  @column_names ||= columns.map(&:name)
end

#columnsArray

All columns

Returns:

  • (Array)


113
114
115
# File 'lib/dbf/table.rb', line 113

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:



121
122
123
# File 'lib/dbf/table.rb', line 121

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

#encode_string(string) ⇒ String

Encode string

Parameters:

  • string (String)

Returns:

  • (String)


220
221
222
# File 'lib/dbf/table.rb', line 220

def encode_string(string) # :nodoc:
  string.force_encoding(@encoding).encode(Encoding.default_external, undef: :replace, invalid: :replace)
end

#filenameString

Returns:

  • (String)


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

def filename
  return unless @data.respond_to?(:path)

  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 (Integer, Symbol)

    command

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

    options Hash of search parameters

Yields:



157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/dbf/table.rb', line 157

def find(command, options = {}, &block)
  case command
  when Integer
    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)


171
172
173
# File 'lib/dbf/table.rb', line 171

def has_memo_file?
  !!@memo
end

#header_encodingEncoding

Encoding specified in the file header

Returns:

  • (Encoding)


227
228
229
# File 'lib/dbf/table.rb', line 227

def header_encoding
  header.encoding
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 (Integer)

Returns:

Raises:



186
187
188
189
190
191
192
193
194
# File 'lib/dbf/table.rb', line 186

def record(index)
  raise DBF::NoColumnsDefined, 'The DBF file has no columns defined' if columns.empty?

  seek_to_record(index)
  return nil if deleted_record?

  record_data = @data.read(record_length)
  DBF::Record.new(record_data, columns, version, @memo)
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



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

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

#version_descriptionString

Human readable version description

Returns:

  • (String)


212
213
214
# File 'lib/dbf/table.rb', line 212

def version_description
  VERSIONS[version]
end