dbf 5.1.1 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/README.md +19 -9
  4. data/bin/dbf +2 -54
  5. data/dbf.gemspec +6 -9
  6. data/lib/dbf/cli.rb +95 -0
  7. data/lib/dbf/column.rb +17 -15
  8. data/lib/dbf/column_builder.rb +31 -0
  9. data/lib/dbf/column_type.rb +66 -16
  10. data/lib/dbf/database/foxpro.rb +19 -32
  11. data/lib/dbf/encoder.rb +116 -0
  12. data/lib/dbf/encodings.rb +8 -0
  13. data/lib/dbf/file_handler.rb +36 -0
  14. data/lib/dbf/find.rb +54 -0
  15. data/lib/dbf/header.rb +5 -8
  16. data/lib/dbf/memo/base.rb +2 -0
  17. data/lib/dbf/memo/dbase3.rb +2 -2
  18. data/lib/dbf/memo/dbase4.rb +2 -2
  19. data/lib/dbf/memo/foxpro.rb +14 -7
  20. data/lib/dbf/record.rb +60 -34
  21. data/lib/dbf/record_context.rb +5 -0
  22. data/lib/dbf/record_iterator.rb +35 -0
  23. data/lib/dbf/schema.rb +21 -21
  24. data/lib/dbf/table.rb +50 -181
  25. data/lib/dbf/version.rb +1 -1
  26. data/lib/dbf/version_config.rb +79 -0
  27. data/lib/dbf.rb +8 -0
  28. metadata +17 -64
  29. data/spec/dbf/column_spec.rb +0 -287
  30. data/spec/dbf/database/foxpro_spec.rb +0 -53
  31. data/spec/dbf/encoding_spec.rb +0 -49
  32. data/spec/dbf/file_formats_spec.rb +0 -221
  33. data/spec/dbf/record_spec.rb +0 -116
  34. data/spec/dbf/table_spec.rb +0 -377
  35. data/spec/fixtures/cp1251.dbf +0 -0
  36. data/spec/fixtures/cp1251_summary.txt +0 -12
  37. data/spec/fixtures/dbase_02.dbf +0 -0
  38. data/spec/fixtures/dbase_02_summary.txt +0 -23
  39. data/spec/fixtures/dbase_03.dbf +0 -0
  40. data/spec/fixtures/dbase_03_cyrillic.dbf +0 -0
  41. data/spec/fixtures/dbase_03_cyrillic_summary.txt +0 -11
  42. data/spec/fixtures/dbase_03_summary.txt +0 -40
  43. data/spec/fixtures/dbase_30.dbf +0 -0
  44. data/spec/fixtures/dbase_30.fpt +0 -0
  45. data/spec/fixtures/dbase_30_summary.txt +0 -154
  46. data/spec/fixtures/dbase_31.dbf +0 -0
  47. data/spec/fixtures/dbase_31_summary.txt +0 -20
  48. data/spec/fixtures/dbase_32.dbf +0 -0
  49. data/spec/fixtures/dbase_32_summary.txt +0 -11
  50. data/spec/fixtures/dbase_83.dbf +0 -0
  51. data/spec/fixtures/dbase_83.dbt +0 -0
  52. data/spec/fixtures/dbase_83_missing_memo.dbf +0 -0
  53. data/spec/fixtures/dbase_83_missing_memo_record_0.yml +0 -16
  54. data/spec/fixtures/dbase_83_record_0.yml +0 -16
  55. data/spec/fixtures/dbase_83_record_9.yml +0 -23
  56. data/spec/fixtures/dbase_83_schema_ar.txt +0 -19
  57. data/spec/fixtures/dbase_83_schema_sq.txt +0 -21
  58. data/spec/fixtures/dbase_83_schema_sq_lim.txt +0 -21
  59. data/spec/fixtures/dbase_83_summary.txt +0 -24
  60. data/spec/fixtures/dbase_8b.dbf +0 -0
  61. data/spec/fixtures/dbase_8b.dbt +0 -0
  62. data/spec/fixtures/dbase_8b_summary.txt +0 -15
  63. data/spec/fixtures/dbase_8c.dbf +0 -0
  64. data/spec/fixtures/dbase_f5.dbf +0 -0
  65. data/spec/fixtures/dbase_f5.fpt +0 -0
  66. data/spec/fixtures/dbase_f5_summary.txt +0 -68
  67. data/spec/fixtures/foxprodb/FOXPRO-DB-TEST.DBC +0 -0
  68. data/spec/fixtures/foxprodb/FOXPRO-DB-TEST.DCT +0 -0
  69. data/spec/fixtures/foxprodb/FOXPRO-DB-TEST.DCX +0 -0
  70. data/spec/fixtures/foxprodb/calls.CDX +0 -0
  71. data/spec/fixtures/foxprodb/calls.FPT +0 -0
  72. data/spec/fixtures/foxprodb/calls.dbf +0 -0
  73. data/spec/fixtures/foxprodb/contacts.CDX +0 -0
  74. data/spec/fixtures/foxprodb/contacts.FPT +0 -0
  75. data/spec/fixtures/foxprodb/contacts.dbf +0 -0
  76. data/spec/fixtures/foxprodb/setup.CDX +0 -0
  77. data/spec/fixtures/foxprodb/setup.dbf +0 -0
  78. data/spec/fixtures/foxprodb/types.CDX +0 -0
  79. data/spec/fixtures/foxprodb/types.dbf +0 -0
  80. data/spec/fixtures/polygon.dbf +0 -0
  81. data/spec/spec_helper.rb +0 -35
@@ -1,287 +0,0 @@
1
- # frozen_string_literal: true
2
- # encoding: ascii-8bit
3
-
4
- require 'spec_helper'
5
-
6
- RSpec.describe DBF::Column do
7
- let(:table) { DBF::Table.new fixture('dbase_30.dbf') }
8
-
9
- context 'when initialized' do
10
- let(:column) { DBF::Column.new table, 'ColumnName', 'N', 1, 0 }
11
-
12
- it 'sets :name accessor' do
13
- expect(column.name).to eq 'ColumnName'
14
- end
15
-
16
- it 'sets :type accessor' do
17
- expect(column.type).to eq 'N'
18
- end
19
-
20
- it 'sets the #length accessor' do
21
- expect(column.length).to eq 1
22
- end
23
-
24
- it 'sets the #decimal accessor' do
25
- expect(column.decimal).to eq 0
26
- end
27
-
28
- it 'accepts length of 0' do
29
- column = DBF::Column.new table, 'ColumnName', 'N', 0, 0
30
- expect(column.length).to eq 0
31
- end
32
-
33
- describe 'with length less than 0' do
34
- it 'raises DBF::Column::LengthError' do
35
- expect { DBF::Column.new table, 'ColumnName', 'N', -1, 0 }.to raise_error(DBF::Column::LengthError)
36
- end
37
- end
38
-
39
- describe 'with empty column name' do
40
- it 'raises DBF::Column::NameError' do
41
- expect { DBF::Column.new table, '', 'N', 1, 0 }.to raise_error(DBF::Column::NameError)
42
- end
43
- end
44
- end
45
-
46
- describe '#type_cast' do
47
- context 'with type N (number)' do
48
- context 'when value is empty' do
49
- it 'returns nil' do
50
- value = ''
51
- column = DBF::Column.new table, 'ColumnName', 'N', 5, 2
52
- expect(column.type_cast(value)).to be_nil
53
- end
54
- end
55
-
56
- context 'with 0 length' do
57
- it 'returns nil' do
58
- column = DBF::Column.new table, 'ColumnName', 'N', 0, 0
59
- expect(column.type_cast('')).to be_nil
60
- end
61
- end
62
-
63
- context 'with 0 decimals' do
64
- it 'casts value to Integer' do
65
- value = '135'
66
- column = DBF::Column.new table, 'ColumnName', 'N', 3, 0
67
- expect(column.type_cast(value)).to eq 135
68
- end
69
-
70
- it 'supports negative Integer' do
71
- value = '-135'
72
- column = DBF::Column.new table, 'ColumnName', 'N', 3, 0
73
- expect(column.type_cast(value)).to eq(-135)
74
- end
75
- end
76
-
77
- context 'with more than 0 decimals' do
78
- it 'casts value to Float' do
79
- value = '13.5'
80
- column = DBF::Column.new table, 'ColumnName', 'N', 2, 1
81
- expect(column.type_cast(value)).to eq 13.5
82
- end
83
-
84
- it 'casts negative value to Float' do
85
- value = '-13.5'
86
- column = DBF::Column.new table, 'ColumnName', 'N', 2, 1
87
- expect(column.type_cast(value)).to eq(-13.5)
88
- end
89
- end
90
- end
91
-
92
- context 'with type F (float)' do
93
- context 'with 0 length' do
94
- it 'returns nil' do
95
- column = DBF::Column.new table, 'ColumnName', 'F', 0, 0
96
- expect(column.type_cast('')).to be_nil
97
- end
98
- end
99
-
100
- it 'casts value to Float' do
101
- value = '135'
102
- column = DBF::Column.new table, 'ColumnName', 'F', 3, 0
103
- expect(column.type_cast(value)).to eq 135.0
104
- end
105
-
106
- it 'casts negative value to Float' do
107
- value = '-135'
108
- column = DBF::Column.new table, 'ColumnName', 'F', 3, 0
109
- expect(column.type_cast(value)).to eq(-135.0)
110
- end
111
- end
112
-
113
- context 'with type B (binary)' do
114
- context 'with Foxpro dbf' do
115
- it 'casts to float' do
116
- column = DBF::Column.new table, 'ColumnName', 'B', 1, 2
117
- expect(column.type_cast("\xEC\x51\xB8\x1E\x85\x6B\x31\x40")).to be_a(Float)
118
- expect(column.type_cast("\xEC\x51\xB8\x1E\x85\x6B\x31\x40")).to eq 17.42
119
- end
120
-
121
- it 'stores original precision' do
122
- column = DBF::Column.new table, 'ColumnName', 'B', 1, 0
123
- expect(column.type_cast("\xEC\x51\xB8\x1E\x85\x6B\x31\x40")).to be_a(Float)
124
- expect(column.type_cast("\xEC\x51\xB8\x1E\x85\x6B\x31\x40")).to eq 17.42
125
- end
126
-
127
- it 'supports negative binary' do
128
- column = DBF::Column.new table, 'ColumnName', 'B', 1, 2
129
- expect(column.type_cast("\x00\x00\x00\x00\x00\xC0\x65\xC0")).to be_a(Float)
130
- expect(column.type_cast("\x00\x00\x00\x00\x00\xC0\x65\xC0")).to eq(-174.0)
131
- end
132
- end
133
- end
134
-
135
- context 'with type I (integer)' do
136
- context 'with 0 length' do
137
- it 'returns nil' do
138
- column = DBF::Column.new table, 'ColumnName', 'I', 0, 0
139
- expect(column.type_cast('')).to be_nil
140
- end
141
- end
142
-
143
- it 'casts value to Integer' do
144
- value = "\203\171\001\000"
145
- column = DBF::Column.new table, 'ColumnName', 'I', 3, 0
146
- expect(column.type_cast(value)).to eq 96_643
147
- end
148
-
149
- it 'supports negative Integer' do
150
- value = "\x24\xE1\xFF\xFF"
151
- column = DBF::Column.new table, 'ColumnName', 'I', 3, 0
152
- expect(column.type_cast(value)).to eq(-7900)
153
- end
154
- end
155
-
156
- context 'with type L (logical/boolean)' do
157
- let(:column) { DBF::Column.new table, 'ColumnName', 'L', 1, 0 }
158
-
159
- it "casts 'y' to true" do
160
- expect(column.type_cast('y')).to be true
161
- end
162
-
163
- it "casts 't' to true" do
164
- expect(column.type_cast('t')).to be true
165
- end
166
-
167
- it "casts value other than 't' or 'y' to false" do
168
- expect(column.type_cast('n')).to be false
169
- end
170
-
171
- context 'with 0 length' do
172
- it 'returns nil' do
173
- column = DBF::Column.new table, 'ColumnName', 'L', 0, 0
174
- expect(column.type_cast('')).to be_nil
175
- end
176
- end
177
- end
178
-
179
- context 'with type T (datetime)' do
180
- let(:column) { DBF::Column.new table, 'ColumnName', 'T', 16, 0 }
181
-
182
- context 'with valid datetime' do
183
- it 'casts to DateTime' do
184
- expect(column.type_cast("Nl%\000\300Z\252\003")).to eq Time.parse('2002-10-10T17:04:56+00:00')
185
- end
186
- end
187
-
188
- context 'with invalid datetime' do
189
- it 'casts to nil' do
190
- expect(column.type_cast("Nl%\000\000A\000\999")).to be_nil
191
- end
192
- end
193
-
194
- context 'with 0 length' do
195
- it 'returns nil' do
196
- column = DBF::Column.new table, 'ColumnName', 'T', 0, 0
197
- expect(column.type_cast('')).to be_nil
198
- end
199
- end
200
- end
201
-
202
- context 'with type D (date)' do
203
- let(:column) { DBF::Column.new table, 'ColumnName', 'D', 8, 0 }
204
-
205
- context 'with valid date' do
206
- it 'casts to Date' do
207
- expect(column.type_cast('20050712')).to eq Date.new(2005, 7, 12)
208
- end
209
- end
210
-
211
- context 'with invalid date' do
212
- it 'casts to nil' do
213
- expect(column.type_cast('000000000')).to be_nil
214
- end
215
- end
216
-
217
- context 'with 0 length' do
218
- it 'returns nil' do
219
- column = DBF::Column.new table, 'ColumnName', 'D', 0, 0
220
- expect(column.type_cast('')).to be_nil
221
- end
222
- end
223
- end
224
-
225
- context 'with type M (memo)' do
226
- it 'casts to string' do
227
- column = DBF::Column.new table, 'ColumnName', 'M', 3, 0
228
- expect(column.type_cast('abc')).to eq 'abc'
229
- end
230
-
231
- it 'casts nil to nil' do
232
- column = DBF::Column.new table, 'ColumnName', 'M', 3, 0
233
- expect(column.type_cast(nil)).to be_nil
234
- end
235
-
236
- context 'with 0 length' do
237
- it 'returns nil' do
238
- column = DBF::Column.new table, 'ColumnName', 'M', 0, 0
239
- expect(column.type_cast('')).to be_nil
240
- end
241
- end
242
- end
243
-
244
- context 'with type G (memo)' do
245
- it 'returns binary data' do
246
- column = DBF::Column.new table, 'ColumnName', 'G', 3, 0
247
- expect(column.type_cast("\000\013\120")).to eq "\000\013\120"
248
- expect(column.type_cast("\000\013\120").encoding).to eq Encoding::ASCII_8BIT
249
- end
250
-
251
- it 'casts nil to nil' do
252
- column = DBF::Column.new table, 'ColumnName', 'G', 3, 0
253
- expect(column.type_cast(nil)).to be_nil
254
- end
255
-
256
- context 'with 0 length' do
257
- it 'returns nil' do
258
- column = DBF::Column.new table, 'ColumnName', 'G', 0, 0
259
- expect(column.type_cast('')).to be_nil
260
- end
261
- end
262
- end
263
- end
264
-
265
- context 'with type Y (currency)' do
266
- let(:column) { DBF::Column.new table, 'ColumnName', 'Y', 8, 4 }
267
-
268
- it 'casts to float' do
269
- expect(column.type_cast(" \xBF\x02\x00\x00\x00\x00\x00")).to eq 18.0
270
- end
271
-
272
- it 'supports negative currency' do
273
- expect(column.type_cast("\xFC\xF0\xF0\xFE\xFF\xFF\xFF\xFF")).to eq(-1776.41)
274
- end
275
-
276
- it 'supports 64bit negative currency' do
277
- expect(column.type_cast("pN'9\xFF\xFF\xFF\xFF")).to eq(-333_609.0)
278
- end
279
-
280
- context 'with 0 length' do
281
- it 'returns nil' do
282
- column = DBF::Column.new table, 'ColumnName', 'Y', 0, 0
283
- expect(column.type_cast('')).to be_nil
284
- end
285
- end
286
- end
287
- end
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- RSpec.describe DBF::Database::Foxpro do
6
- let(:dbf_path) { fixture('foxprodb/FOXPRO-DB-TEST.DBC') }
7
- let(:db) { DBF::Database::Foxpro.new(dbf_path) }
8
-
9
- describe '#initialize' do
10
- describe 'when given a path to an existing dbc file' do
11
- it 'does not raise an error' do
12
- expect { DBF::Database::Foxpro.new dbf_path }.to_not raise_error
13
- end
14
- end
15
-
16
- describe 'when given a path to a non-existent dbf file' do
17
- it 'raises a DBF::FileNotFound error' do
18
- expect { DBF::Database::Foxpro.new 'x' }.to raise_error(DBF::FileNotFoundError, 'file not found: x')
19
- end
20
- end
21
-
22
- describe 'it loads the example db correctly' do
23
- it 'shows a correct list of tables' do
24
- expect(db.table_names.sort).to eq(%w[contacts calls setup types].sort)
25
- end
26
- end
27
- end
28
-
29
- describe '#table' do
30
- describe 'when accessing related tables' do
31
- let(:db) { DBF::Database::Foxpro.new(dbf_path) }
32
-
33
- it 'loads an existing related table' do
34
- expect(db.contacts.record_count).to eq 5
35
- end
36
-
37
- it 'supports a long table field name' do
38
- expect(db.contacts.record(1).spouses_interests).to eq 'Tennis, golf'
39
- end
40
-
41
- it 'loads an existing related table with wrong filename casing' do
42
- expect(db.calls.record_count).to eq 16
43
- end
44
- end
45
- end
46
-
47
- describe '#table_path' do
48
- it 'returns an absolute path' do
49
- expect(db.table_path('contacts')).to eq File.expand_path('spec/fixtures/foxprodb/contacts.dbf')
50
- end
51
- end
52
-
53
- end
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- RSpec.describe 'DBF::Table' do
6
- context 'with default encoding' do
7
- let(:dbf_path) { fixture('dbase_03_cyrillic.dbf') }
8
- let(:table) { DBF::Table.new dbf_path }
9
-
10
- it 'defaults to UTF-8 encoding' do
11
- expect(table.encoding).to eq Encoding::UTF_8
12
- end
13
-
14
- it 'uses the table encoding for column encoding' do
15
- column = table.columns.first
16
- expect(column.encoding).to eq table.encoding
17
- end
18
-
19
- it 'encodes column names' do
20
- expect(table.column_names).to eq %w[ШАР ПЛОЩА]
21
- end
22
-
23
- it 'encodes record values' do
24
- expect(table.record(0).attributes['ШАР']).to eq 'Номер'
25
- end
26
- end
27
-
28
- context 'with embedded encoding' do
29
- let(:dbf_path) { fixture('cp1251.dbf') }
30
- let(:table) { DBF::Table.new dbf_path }
31
-
32
- it 'defaults to UTF-8 encoding' do
33
- expect(table.encoding).to eq 'cp1251'
34
- end
35
-
36
- it 'uses the table encoding for column encoding' do
37
- column = table.columns.first
38
- expect(column.encoding).to eq table.encoding
39
- end
40
-
41
- it 'encodes column names' do
42
- expect(table.column_names).to eq %w[RN NAME]
43
- end
44
-
45
- it 'encodes record values' do
46
- expect(table.record(0).attributes['NAME']).to eq 'амбулаторно-поликлиническое'
47
- end
48
- end
49
- end
@@ -1,221 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- RSpec.shared_examples_for 'DBF' do
6
- let(:header_record_length) { table.instance_eval { header.record_length } }
7
- let(:sum_of_column_lengths) { table.columns.inject(1) { |sum, column| sum + column.length } }
8
-
9
- specify 'sum of column lengths should equal record length specified in header plus one' do
10
- expect(header_record_length).to eq sum_of_column_lengths
11
- end
12
-
13
- specify 'records should be instances of DBF::Record' do
14
- expect(table).to all be_a(DBF::Record)
15
- end
16
-
17
- specify 'record count should be the same as reported in the header' do
18
- expect(table.entries.size).to eq table.record_count
19
- end
20
-
21
- specify 'column names should not be blank' do
22
- table.columns.each do |column|
23
- expect(column.name).to_not be_empty
24
- end
25
- end
26
-
27
- specify 'column types should be valid' do
28
- valid_column_types = %w[C N L D M F B G P Y T I V X @ O + 0]
29
- table.columns.each do |column|
30
- expect(valid_column_types).to include(column.type)
31
- end
32
- end
33
-
34
- specify 'column lengths should be instances of Integer' do
35
- table.columns.each do |column|
36
- expect(column.length).to be_a(Integer)
37
- end
38
- end
39
-
40
- specify 'column lengths should be larger than 0' do
41
- table.columns.each do |column|
42
- expect(column.length).to be > 0
43
- end
44
- end
45
-
46
- specify 'column decimals should be instances of Integer' do
47
- table.columns.each do |column|
48
- expect(column.decimal).to be_a(Integer)
49
- end
50
- end
51
- end
52
-
53
- RSpec.describe DBF, 'of type 02 (FoxBase)' do
54
- let(:table) { DBF::Table.new fixture('dbase_02.dbf') }
55
-
56
- it_behaves_like 'DBF'
57
-
58
- it 'reports the correct version number' do
59
- expect(table.version).to eq '02'
60
- end
61
-
62
- it 'reports the correct version description' do
63
- expect(table.version_description).to eq 'FoxBase'
64
- end
65
-
66
- it 'determines the number of records' do
67
- expect(table.record_count).to eq 9
68
- end
69
- end
70
-
71
- RSpec.describe DBF, 'of type 03 (dBase III without memo file)' do
72
- let(:table) { DBF::Table.new fixture('dbase_03.dbf') }
73
-
74
- it_behaves_like 'DBF'
75
-
76
- it 'reports the correct version number' do
77
- expect(table.version).to eq '03'
78
- end
79
-
80
- it 'reports the correct version description' do
81
- expect(table.version_description).to eq 'dBase III without memo file'
82
- end
83
-
84
- it 'determines the number of records' do
85
- expect(table.record_count).to eq 14
86
- end
87
- end
88
-
89
- RSpec.describe DBF, 'of type 30 (Visual FoxPro)' do
90
- let(:table) { DBF::Table.new fixture('dbase_30.dbf') }
91
-
92
- it_behaves_like 'DBF'
93
-
94
- it 'reports the correct version number' do
95
- expect(table.version).to eq '30'
96
- end
97
-
98
- it 'reports the correct version description' do
99
- expect(table.version_description).to eq 'Visual FoxPro'
100
- end
101
-
102
- it 'determines the number of records' do
103
- expect(table.record_count).to eq 34
104
- end
105
-
106
- it 'reads memo data' do
107
- expect(table.record(3).classes).to match(/\AAgriculture.*Farming\r\n\Z/m)
108
- end
109
- end
110
-
111
- RSpec.describe DBF, 'of type 31 (Visual FoxPro with AutoIncrement field)' do
112
- let(:table) { DBF::Table.new fixture('dbase_31.dbf') }
113
-
114
- it_behaves_like 'DBF'
115
-
116
- it 'has a dBase version of 31' do
117
- expect(table.version).to eq '31'
118
- end
119
-
120
- it 'reports the correct version description' do
121
- expect(table.version_description).to eq 'Visual FoxPro with AutoIncrement field'
122
- end
123
-
124
- it 'determines the number of records' do
125
- expect(table.record_count).to eq 77
126
- end
127
- end
128
-
129
- RSpec.describe DBF, 'of type 32 (Visual FoxPro with field type Varchar or Varbinary)' do
130
- let(:table) { DBF::Table.new fixture('dbase_32.dbf') }
131
-
132
- it_behaves_like 'DBF'
133
-
134
- it 'has a dBase version of 32' do
135
- expect(table.version).to eq '32'
136
- end
137
-
138
- it 'reports the correct version description' do
139
- expect(table.version_description).to eq 'Visual FoxPro with field type Varchar or Varbinary'
140
- end
141
-
142
- it 'determines the number of records' do
143
- expect(table.record_count).to eq 1
144
- end
145
- end
146
-
147
- RSpec.describe DBF, 'of type 83 (dBase III with memo file)' do
148
- let(:table) { DBF::Table.new fixture('dbase_83.dbf') }
149
-
150
- it_behaves_like 'DBF'
151
-
152
- it 'reports the correct version number' do
153
- expect(table.version).to eq '83'
154
- end
155
-
156
- it 'reports the correct version description' do
157
- expect(table.version_description).to eq 'dBase III with memo file'
158
- end
159
-
160
- it 'determines the number of records' do
161
- expect(table.record_count).to eq 67
162
- end
163
- end
164
-
165
- RSpec.describe DBF, 'of type 8b (dBase IV with memo file)' do
166
- let(:table) { DBF::Table.new fixture('dbase_8b.dbf') }
167
-
168
- it_behaves_like 'DBF'
169
-
170
- it 'reports the correct version number' do
171
- expect(table.version).to eq '8b'
172
- end
173
-
174
- it 'reports the correct version description' do
175
- expect(table.version_description).to eq 'dBase IV with memo file'
176
- end
177
-
178
- it 'determines the number of records' do
179
- expect(table.record_count).to eq 10
180
- end
181
- end
182
-
183
- RSpec.describe DBF, 'of type 8c (unknown)' do
184
- let(:table) { DBF::Table.new fixture('dbase_8c.dbf') }
185
-
186
- it_behaves_like 'DBF'
187
-
188
- it 'reports the correct version number' do
189
- expect(table.version).to eq '8c'
190
- end
191
-
192
- it 'reports the correct version description' do
193
- expect(table.version_description).to eq 'dBase 7'
194
- end
195
-
196
- it 'determines the number of records' do
197
- expect(table.record_count).to eq 10
198
- end
199
- end
200
-
201
- RSpec.describe DBF, 'of type f5 (FoxPro with memo file)' do
202
- let(:table) { DBF::Table.new fixture('dbase_f5.dbf') }
203
-
204
- it_behaves_like 'DBF'
205
-
206
- it 'reports the correct version number' do
207
- expect(table.version).to eq 'f5'
208
- end
209
-
210
- it 'reports the correct version description' do
211
- expect(table.version_description).to eq 'FoxPro with memo file'
212
- end
213
-
214
- it 'determines the number of records' do
215
- expect(table.record_count).to eq 975
216
- end
217
-
218
- it 'reads memo data' do
219
- expect(table.record(3).datn.to_s).to eq '1870-06-30'
220
- end
221
- end