dbf 3.1.3 → 4.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/Gemfile +3 -1
- data/Gemfile.lock +8 -3
- data/LICENSE +1 -1
- data/README.md +5 -4
- data/bin/dbf +2 -2
- data/dbf.gemspec +1 -1
- data/lib/dbf.rb +1 -0
- data/lib/dbf/column.rb +3 -8
- data/lib/dbf/column_type.rb +9 -9
- data/lib/dbf/database/foxpro.rb +1 -3
- data/lib/dbf/memo/base.rb +1 -0
- data/lib/dbf/memo/dbase4.rb +1 -1
- data/lib/dbf/memo/foxpro.rb +2 -3
- data/lib/dbf/record.rb +1 -1
- data/lib/dbf/table.rb +14 -20
- data/lib/dbf/version.rb +1 -1
- data/spec/dbf/column_spec.rb +9 -9
- data/spec/dbf/file_formats_spec.rb +25 -25
- data/spec/dbf/record_spec.rb +5 -5
- data/spec/dbf/table_spec.rb +14 -14
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c958b14933bbb6d5a9f1e4489b61603d68e43d5fc39331267aac586c324a9afb
|
4
|
+
data.tar.gz: 43714e5ff6c6c67f5e0d77fd0c6f7485466545ace2e3d911937076bb74ff4a23
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c1b0f3d7edf0b5ec26d748c1c1f67be7877c4f150cb9adb14d0eb2994c3515ba466d803e3bc94c3111608c574908b54d1fd69077591e676ca75ea24cb81db6be
|
7
|
+
data.tar.gz: 28358a00908e6f8bdaec6e74731b9961380a87c67e43dab21971bd686b7aef6fa6ba554faedee3168082a62125fd4dda24d23b257b5f1fa536b3313a8e2ef7a8
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
dbf (
|
4
|
+
dbf (4.0.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
@@ -27,6 +27,7 @@ GEM
|
|
27
27
|
guard (~> 2.1)
|
28
28
|
guard-compat (~> 1.1)
|
29
29
|
rspec (>= 2.99.0, < 4.0)
|
30
|
+
irb (1.0.0)
|
30
31
|
jaro_winkler (1.5.1)
|
31
32
|
listen (3.1.5)
|
32
33
|
rb-fsevent (~> 0.9, >= 0.9.4)
|
@@ -56,7 +57,7 @@ GEM
|
|
56
57
|
rspec-mocks (~> 3.8.0)
|
57
58
|
rspec-core (3.8.0)
|
58
59
|
rspec-support (~> 3.8.0)
|
59
|
-
rspec-expectations (3.8.
|
60
|
+
rspec-expectations (3.8.2)
|
60
61
|
diff-lcs (>= 1.2.0, < 2.0)
|
61
62
|
rspec-support (~> 3.8.0)
|
62
63
|
rspec-mocks (3.8.0)
|
@@ -71,6 +72,8 @@ GEM
|
|
71
72
|
rainbow (>= 2.2.2, < 4.0)
|
72
73
|
ruby-progressbar (~> 1.7)
|
73
74
|
unicode-display_width (~> 1.0, >= 1.0.1)
|
75
|
+
rubocop-rspec (1.30.0)
|
76
|
+
rubocop (>= 0.58.0)
|
74
77
|
ruby-progressbar (1.10.0)
|
75
78
|
ruby_dep (1.5.0)
|
76
79
|
shellany (0.0.1)
|
@@ -86,9 +89,11 @@ DEPENDENCIES
|
|
86
89
|
dbf!
|
87
90
|
guard
|
88
91
|
guard-rspec
|
92
|
+
irb
|
89
93
|
rake
|
90
94
|
rspec
|
91
95
|
rubocop
|
96
|
+
rubocop-rspec
|
92
97
|
|
93
98
|
BUNDLED WITH
|
94
|
-
|
99
|
+
2.0.0
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -16,14 +16,15 @@ database files
|
|
16
16
|
subject line
|
17
17
|
* Change log: <https://github.com/infused/dbf/blob/master/CHANGELOG.md>
|
18
18
|
|
19
|
-
NOTE:
|
19
|
+
NOTE: Beginninf with version 4 we have dropped support for Ruby 2.0, 2.1, 2.2, and 2.3. If you need support for these older Rubies, please use 3.0.x (https://github.com/infused.org/dbf/tree/3_stable)
|
20
|
+
|
21
|
+
NOTE: Beginning with version 3 we have dropped support for Ruby 1.8 and 1.9. If you need support for older Rubies, please use 2.0.x (https://github.com/infused/dbf/tree/2_stable)
|
20
22
|
|
21
23
|
## Compatibility
|
22
24
|
|
23
25
|
DBF is tested to work with the following versions of Ruby:
|
24
26
|
|
25
|
-
*
|
26
|
-
* JRuby 1.7.x
|
27
|
+
* Ruby 2.3.x, 2.4.x, 2.5.x, 2.6.x
|
27
28
|
|
28
29
|
## Installation
|
29
30
|
|
@@ -272,7 +273,7 @@ for a full list of supported column types.
|
|
272
273
|
|
273
274
|
## License
|
274
275
|
|
275
|
-
Copyright (c) 2006-
|
276
|
+
Copyright (c) 2006-2019 Keith Morrison <<keithm@infused.org>>
|
276
277
|
|
277
278
|
Permission is hereby granted, free of charge, to any person
|
278
279
|
obtaining a copy of this software and associated documentation
|
data/bin/dbf
CHANGED
@@ -9,7 +9,7 @@ params = ARGV.getopts('h', 's', 'a', 'c', 'r', 'v')
|
|
9
9
|
if params['v']
|
10
10
|
puts "dbf version: #{DBF::VERSION}"
|
11
11
|
|
12
|
-
elsif params['h']
|
12
|
+
elsif params['h']
|
13
13
|
puts "usage: #{File.basename(__FILE__)} [-h|-s|-a|-c|-r] filename"
|
14
14
|
puts ' -h = print this message'
|
15
15
|
puts ' -v = print the DBF gem version'
|
@@ -46,7 +46,7 @@ else
|
|
46
46
|
puts 'Name Type Length Decimal'
|
47
47
|
puts '-' * 78
|
48
48
|
table.columns.each do |f|
|
49
|
-
puts '%-16s %-10s %-10s %-10s'
|
49
|
+
puts format('%-16s %-10s %-10s %-10s', f.name, f.type, f.length, f.decimal)
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
data/dbf.gemspec
CHANGED
data/lib/dbf.rb
CHANGED
data/lib/dbf/column.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
module DBF
|
2
2
|
class Column
|
3
|
+
extend Forwardable
|
4
|
+
|
3
5
|
class LengthError < StandardError
|
4
6
|
end
|
5
7
|
|
@@ -7,6 +9,7 @@ module DBF
|
|
7
9
|
end
|
8
10
|
|
9
11
|
attr_reader :table, :name, :type, :length, :decimal
|
12
|
+
def_delegator :type_cast_class, :type_cast
|
10
13
|
|
11
14
|
TYPE_CAST_CLASS = {
|
12
15
|
N: ColumnType::Number,
|
@@ -56,14 +59,6 @@ module DBF
|
|
56
59
|
{name: name, type: type, length: length, decimal: decimal}
|
57
60
|
end
|
58
61
|
|
59
|
-
# Cast value to native type
|
60
|
-
#
|
61
|
-
# @param [String] value
|
62
|
-
# @return [Integer, Float, Date, DateTime, Boolean, String]
|
63
|
-
def type_cast(value)
|
64
|
-
type_cast_class.type_cast(value)
|
65
|
-
end
|
66
|
-
|
67
62
|
# Underscored name
|
68
63
|
#
|
69
64
|
# This is the column name converted to underscore format.
|
data/lib/dbf/column_type.rb
CHANGED
@@ -15,7 +15,7 @@ module DBF
|
|
15
15
|
end
|
16
16
|
|
17
17
|
class Nil < Base
|
18
|
-
def type_cast(
|
18
|
+
def type_cast(_value)
|
19
19
|
nil
|
20
20
|
end
|
21
21
|
end
|
@@ -23,19 +23,20 @@ module DBF
|
|
23
23
|
class Number < Base
|
24
24
|
def type_cast(value)
|
25
25
|
return nil if value.strip.empty?
|
26
|
+
|
26
27
|
@decimal.zero? ? value.to_i : value.to_f
|
27
28
|
end
|
28
29
|
end
|
29
30
|
|
30
31
|
class Currency < Base
|
31
32
|
def type_cast(value)
|
32
|
-
(value.
|
33
|
+
(value.unpack1('q<') / 10_000.0).to_f
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
36
37
|
class SignedLong < Base
|
37
38
|
def type_cast(value)
|
38
|
-
value.
|
39
|
+
value.unpack1('l<')
|
39
40
|
end
|
40
41
|
end
|
41
42
|
|
@@ -47,20 +48,20 @@ module DBF
|
|
47
48
|
|
48
49
|
class Double < Base
|
49
50
|
def type_cast(value)
|
50
|
-
value.
|
51
|
+
value.unpack1('E')
|
51
52
|
end
|
52
53
|
end
|
53
54
|
|
54
55
|
class Boolean < Base
|
55
56
|
def type_cast(value)
|
56
|
-
value.strip
|
57
|
+
value.strip.match? /^(y|t)$/i
|
57
58
|
end
|
58
59
|
end
|
59
60
|
|
60
61
|
class Date < Base
|
61
62
|
def type_cast(value)
|
62
|
-
value
|
63
|
-
rescue
|
63
|
+
value.match?(/\d{8}/) && ::Date.strptime(value, '%Y%m%d')
|
64
|
+
rescue StandardError
|
64
65
|
nil
|
65
66
|
end
|
66
67
|
end
|
@@ -70,7 +71,7 @@ module DBF
|
|
70
71
|
days, msecs = value.unpack('l2')
|
71
72
|
secs = (msecs / 1000).to_i
|
72
73
|
::DateTime.jd(days, (secs / 3600).to_i, (secs / 60).to_i % 60, secs % 60)
|
73
|
-
rescue
|
74
|
+
rescue StandardError
|
74
75
|
nil
|
75
76
|
end
|
76
77
|
end
|
@@ -97,6 +98,5 @@ module DBF
|
|
97
98
|
@encoding ? value.force_encoding(@encoding).encode(*ENCODING_ARGS) : value
|
98
99
|
end
|
99
100
|
end
|
100
|
-
|
101
101
|
end
|
102
102
|
end
|
data/lib/dbf/database/foxpro.rb
CHANGED
@@ -45,9 +45,7 @@ module DBF
|
|
45
45
|
glob = File.join(@dirname, "#{name}.dbf")
|
46
46
|
path = Dir.glob(glob, File::FNM_CASEFOLD).first
|
47
47
|
|
48
|
-
unless path && File.exist?(path)
|
49
|
-
raise DBF::FileNotFoundError, "related table not found: #{name}"
|
50
|
-
end
|
48
|
+
raise DBF::FileNotFoundError, "related table not found: #{name}" unless path && File.exist?(path)
|
51
49
|
|
52
50
|
path
|
53
51
|
end
|
data/lib/dbf/memo/base.rb
CHANGED
data/lib/dbf/memo/dbase4.rb
CHANGED
data/lib/dbf/memo/foxpro.rb
CHANGED
@@ -15,8 +15,7 @@ module DBF
|
|
15
15
|
memo_string = memo_string[0, memo_size]
|
16
16
|
end
|
17
17
|
memo_string
|
18
|
-
|
19
|
-
rescue
|
18
|
+
rescue StandardError
|
20
19
|
nil
|
21
20
|
end
|
22
21
|
|
@@ -25,7 +24,7 @@ module DBF
|
|
25
24
|
def block_size # :nodoc:
|
26
25
|
@block_size ||= begin
|
27
26
|
@data.rewind
|
28
|
-
@data.read(FPT_HEADER_SIZE).
|
27
|
+
@data.read(FPT_HEADER_SIZE).unpack1('x6n') || 0
|
29
28
|
end
|
30
29
|
end
|
31
30
|
end
|
data/lib/dbf/record.rb
CHANGED
data/lib/dbf/table.rb
CHANGED
@@ -5,6 +5,7 @@ module DBF
|
|
5
5
|
# DBF::Table is the primary interface to a single DBF file and provides
|
6
6
|
# methods for enumerating and searching the records.
|
7
7
|
class Table
|
8
|
+
extend Forwardable
|
8
9
|
include Enumerable
|
9
10
|
include ::DBF::Schema
|
10
11
|
|
@@ -40,6 +41,11 @@ module DBF
|
|
40
41
|
attr_accessor :encoding
|
41
42
|
attr_writer :name
|
42
43
|
|
44
|
+
def_delegator :header, :header_length
|
45
|
+
def_delegator :header, :record_count
|
46
|
+
def_delegator :header, :record_length
|
47
|
+
def_delegator :header, :version
|
48
|
+
|
43
49
|
# Opens a DBF::Table
|
44
50
|
# Examples:
|
45
51
|
# # working with a file stored on the filesystem
|
@@ -104,7 +110,7 @@ module DBF
|
|
104
110
|
#
|
105
111
|
# @yield [nil, DBF::Record]
|
106
112
|
def each
|
107
|
-
|
113
|
+
record_count.times { |i| yield record(i) }
|
108
114
|
end
|
109
115
|
|
110
116
|
# @return [String]
|
@@ -169,18 +175,12 @@ module DBF
|
|
169
175
|
def record(index)
|
170
176
|
seek_to_record(index)
|
171
177
|
return nil if deleted_record?
|
172
|
-
|
178
|
+
|
179
|
+
DBF::Record.new(@data.read(record_length), columns, version, @memo)
|
173
180
|
end
|
174
181
|
|
175
182
|
alias row record
|
176
183
|
|
177
|
-
# Total number of records
|
178
|
-
#
|
179
|
-
# @return [Integer]
|
180
|
-
def record_count
|
181
|
-
@record_count ||= header.record_count
|
182
|
-
end
|
183
|
-
|
184
184
|
# Dumps all records to a CSV file. If no filename is given then CSV is
|
185
185
|
# output to STDOUT.
|
186
186
|
#
|
@@ -192,13 +192,6 @@ module DBF
|
|
192
192
|
each { |record| csv << record.to_a }
|
193
193
|
end
|
194
194
|
|
195
|
-
# Internal dBase version number
|
196
|
-
#
|
197
|
-
# @return [String]
|
198
|
-
def version
|
199
|
-
@version ||= header.version
|
200
|
-
end
|
201
|
-
|
202
195
|
# Human readable version description
|
203
196
|
#
|
204
197
|
# @return [String]
|
@@ -222,7 +215,7 @@ module DBF
|
|
222
215
|
|
223
216
|
def deleted_record? # :nodoc:
|
224
217
|
flag = @data.read(1)
|
225
|
-
flag ? flag.
|
218
|
+
flag ? flag.unpack1('a') == '*' : true
|
226
219
|
end
|
227
220
|
|
228
221
|
def end_of_record? # :nodoc:
|
@@ -232,6 +225,7 @@ module DBF
|
|
232
225
|
def find_all(options) # :nodoc:
|
233
226
|
select do |record|
|
234
227
|
next unless record && record.match?(options)
|
228
|
+
|
235
229
|
yield record if block_given?
|
236
230
|
record
|
237
231
|
end
|
@@ -242,7 +236,7 @@ module DBF
|
|
242
236
|
end
|
243
237
|
|
244
238
|
def foxpro? # :nodoc:
|
245
|
-
FOXPRO_VERSIONS.
|
239
|
+
FOXPRO_VERSIONS.key?(version)
|
246
240
|
end
|
247
241
|
|
248
242
|
def header # :nodoc:
|
@@ -290,11 +284,11 @@ module DBF
|
|
290
284
|
end
|
291
285
|
|
292
286
|
def seek(offset) # :nodoc:
|
293
|
-
@data.seek(
|
287
|
+
@data.seek(header_length + offset)
|
294
288
|
end
|
295
289
|
|
296
290
|
def seek_to_record(index) # :nodoc:
|
297
|
-
seek(index *
|
291
|
+
seek(index * record_length)
|
298
292
|
end
|
299
293
|
end
|
300
294
|
end
|
data/lib/dbf/version.rb
CHANGED
data/spec/dbf/column_spec.rb
CHANGED
@@ -69,7 +69,7 @@ RSpec.describe DBF::Column do
|
|
69
69
|
it 'supports negative Integer' do
|
70
70
|
value = '-135'
|
71
71
|
column = DBF::Column.new table, 'ColumnName', 'N', 3, 0
|
72
|
-
expect(column.type_cast(value)).to eq
|
72
|
+
expect(column.type_cast(value)).to eq -135
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
@@ -83,7 +83,7 @@ RSpec.describe DBF::Column do
|
|
83
83
|
it 'casts negative value to Float' do
|
84
84
|
value = '-13.5'
|
85
85
|
column = DBF::Column.new table, 'ColumnName', 'N', 2, 1
|
86
|
-
expect(column.type_cast(value)).to eq
|
86
|
+
expect(column.type_cast(value)).to eq -13.5
|
87
87
|
end
|
88
88
|
end
|
89
89
|
end
|
@@ -105,7 +105,7 @@ RSpec.describe DBF::Column do
|
|
105
105
|
it 'casts negative value to Float' do
|
106
106
|
value = '-135'
|
107
107
|
column = DBF::Column.new table, 'ColumnName', 'F', 3, 0
|
108
|
-
expect(column.type_cast(value)).to eq
|
108
|
+
expect(column.type_cast(value)).to eq -135.0
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
@@ -126,7 +126,7 @@ RSpec.describe DBF::Column do
|
|
126
126
|
it 'supports negative binary' do
|
127
127
|
column = DBF::Column.new table, 'ColumnName', 'B', 1, 2
|
128
128
|
expect(column.type_cast("\x00\x00\x00\x00\x00\xC0\x65\xC0")).to be_a(Float)
|
129
|
-
expect(column.type_cast("\x00\x00\x00\x00\x00\xC0\x65\xC0")).to eq
|
129
|
+
expect(column.type_cast("\x00\x00\x00\x00\x00\xC0\x65\xC0")).to eq -174.0
|
130
130
|
end
|
131
131
|
end
|
132
132
|
end
|
@@ -142,13 +142,13 @@ RSpec.describe DBF::Column do
|
|
142
142
|
it 'casts value to Integer' do
|
143
143
|
value = "\203\171\001\000"
|
144
144
|
column = DBF::Column.new table, 'ColumnName', 'I', 3, 0
|
145
|
-
expect(column.type_cast(value)).to eq
|
145
|
+
expect(column.type_cast(value)).to eq 96_643
|
146
146
|
end
|
147
147
|
|
148
148
|
it 'supports negative Integer' do
|
149
149
|
value = "\x24\xE1\xFF\xFF"
|
150
150
|
column = DBF::Column.new table, 'ColumnName', 'I', 3, 0
|
151
|
-
expect(column.type_cast(value)).to eq
|
151
|
+
expect(column.type_cast(value)).to eq -7900
|
152
152
|
end
|
153
153
|
end
|
154
154
|
|
@@ -203,7 +203,7 @@ RSpec.describe DBF::Column do
|
|
203
203
|
|
204
204
|
context 'with valid date' do
|
205
205
|
it 'casts to Date' do
|
206
|
-
expect(column.type_cast('20050712')).to eq Date.new(2005,7,12)
|
206
|
+
expect(column.type_cast('20050712')).to eq Date.new(2005, 7, 12)
|
207
207
|
end
|
208
208
|
end
|
209
209
|
|
@@ -269,11 +269,11 @@ RSpec.describe DBF::Column do
|
|
269
269
|
end
|
270
270
|
|
271
271
|
it 'supports negative currency' do
|
272
|
-
expect(column.type_cast("\xFC\xF0\xF0\xFE\xFF\xFF\xFF\xFF")).to eq
|
272
|
+
expect(column.type_cast("\xFC\xF0\xF0\xFE\xFF\xFF\xFF\xFF")).to eq -1776.41
|
273
273
|
end
|
274
274
|
|
275
275
|
it 'supports 64bit negative currency' do
|
276
|
-
expect(column.type_cast("pN'9\xFF\xFF\xFF\xFF")).to eq
|
276
|
+
expect(column.type_cast("pN'9\xFF\xFF\xFF\xFF")).to eq -333_609.0
|
277
277
|
end
|
278
278
|
|
279
279
|
context 'and 0 length' do
|
@@ -20,7 +20,7 @@ RSpec.shared_examples_for 'DBF' do
|
|
20
20
|
|
21
21
|
specify 'column names should not be blank' do
|
22
22
|
table.columns.each do |column|
|
23
|
-
expect(column.name).
|
23
|
+
expect(column.name).to_not be_empty
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -53,17 +53,17 @@ end
|
|
53
53
|
RSpec.describe DBF, 'of type 03 (dBase III without memo file)' do
|
54
54
|
let(:table) { DBF::Table.new fixture('dbase_03.dbf') }
|
55
55
|
|
56
|
-
|
56
|
+
it_behaves_like 'DBF'
|
57
57
|
|
58
|
-
it '
|
58
|
+
it 'reports the correct version number' do
|
59
59
|
expect(table.version).to eq '03'
|
60
60
|
end
|
61
61
|
|
62
|
-
it '
|
62
|
+
it 'reports the correct version description' do
|
63
63
|
expect(table.version_description).to eq 'dBase III without memo file'
|
64
64
|
end
|
65
65
|
|
66
|
-
it '
|
66
|
+
it 'determines the number of records' do
|
67
67
|
expect(table.record_count).to eq 14
|
68
68
|
end
|
69
69
|
end
|
@@ -71,17 +71,17 @@ end
|
|
71
71
|
RSpec.describe DBF, 'of type 30 (Visual FoxPro)' do
|
72
72
|
let(:table) { DBF::Table.new fixture('dbase_30.dbf') }
|
73
73
|
|
74
|
-
|
74
|
+
it_behaves_like 'DBF'
|
75
75
|
|
76
|
-
it '
|
76
|
+
it 'reports the correct version number' do
|
77
77
|
expect(table.version).to eq '30'
|
78
78
|
end
|
79
79
|
|
80
|
-
it '
|
80
|
+
it 'reports the correct version description' do
|
81
81
|
expect(table.version_description).to eq 'Visual FoxPro'
|
82
82
|
end
|
83
83
|
|
84
|
-
it '
|
84
|
+
it 'determines the number of records' do
|
85
85
|
expect(table.record_count).to eq 34
|
86
86
|
end
|
87
87
|
|
@@ -93,17 +93,17 @@ end
|
|
93
93
|
RSpec.describe DBF, 'of type 31 (Visual FoxPro with AutoIncrement field)' do
|
94
94
|
let(:table) { DBF::Table.new fixture('dbase_31.dbf') }
|
95
95
|
|
96
|
-
|
96
|
+
it_behaves_like 'DBF'
|
97
97
|
|
98
|
-
it '
|
98
|
+
it 'has a dBase version of 31' do
|
99
99
|
expect(table.version).to eq '31'
|
100
100
|
end
|
101
101
|
|
102
|
-
it '
|
102
|
+
it 'reports the correct version description' do
|
103
103
|
expect(table.version_description).to eq 'Visual FoxPro with AutoIncrement field'
|
104
104
|
end
|
105
105
|
|
106
|
-
it '
|
106
|
+
it 'determines the number of records' do
|
107
107
|
expect(table.record_count).to eq 77
|
108
108
|
end
|
109
109
|
end
|
@@ -111,17 +111,17 @@ end
|
|
111
111
|
RSpec.describe DBF, 'of type 83 (dBase III with memo file)' do
|
112
112
|
let(:table) { DBF::Table.new fixture('dbase_83.dbf') }
|
113
113
|
|
114
|
-
|
114
|
+
it_behaves_like 'DBF'
|
115
115
|
|
116
|
-
it '
|
116
|
+
it 'reports the correct version number' do
|
117
117
|
expect(table.version).to eq '83'
|
118
118
|
end
|
119
119
|
|
120
|
-
it '
|
120
|
+
it 'reports the correct version description' do
|
121
121
|
expect(table.version_description).to eq 'dBase III with memo file'
|
122
122
|
end
|
123
123
|
|
124
|
-
it '
|
124
|
+
it 'determines the number of records' do
|
125
125
|
expect(table.record_count).to eq 67
|
126
126
|
end
|
127
127
|
end
|
@@ -129,17 +129,17 @@ end
|
|
129
129
|
RSpec.describe DBF, 'of type 8b (dBase IV with memo file)' do
|
130
130
|
let(:table) { DBF::Table.new fixture('dbase_8b.dbf') }
|
131
131
|
|
132
|
-
|
132
|
+
it_behaves_like 'DBF'
|
133
133
|
|
134
|
-
it '
|
134
|
+
it 'reports the correct version number' do
|
135
135
|
expect(table.version).to eq '8b'
|
136
136
|
end
|
137
137
|
|
138
|
-
it '
|
138
|
+
it 'reports the correct version description' do
|
139
139
|
expect(table.version_description).to eq 'dBase IV with memo file'
|
140
140
|
end
|
141
141
|
|
142
|
-
it '
|
142
|
+
it 'determines the number of records' do
|
143
143
|
expect(table.record_count).to eq 10
|
144
144
|
end
|
145
145
|
end
|
@@ -147,17 +147,17 @@ end
|
|
147
147
|
RSpec.describe DBF, 'of type f5 (FoxPro with memo file)' do
|
148
148
|
let(:table) { DBF::Table.new fixture('dbase_f5.dbf') }
|
149
149
|
|
150
|
-
|
150
|
+
it_behaves_like 'DBF'
|
151
151
|
|
152
|
-
it '
|
152
|
+
it 'reports the correct version number' do
|
153
153
|
expect(table.version).to eq 'f5'
|
154
154
|
end
|
155
155
|
|
156
|
-
it '
|
156
|
+
it 'reports the correct version description' do
|
157
157
|
expect(table.version_description).to eq 'FoxPro with memo file'
|
158
158
|
end
|
159
159
|
|
160
|
-
it '
|
160
|
+
it 'determines the number of records' do
|
161
161
|
expect(table.record_count).to eq 975
|
162
162
|
end
|
163
163
|
|
data/spec/dbf/record_spec.rb
CHANGED
@@ -6,7 +6,7 @@ RSpec.describe DBF::Record do
|
|
6
6
|
let(:record_0) { YAML.load_file(fixture('dbase_83_record_0.yml')) }
|
7
7
|
let(:record_9) { YAML.load_file(fixture('dbase_83_record_9.yml')) }
|
8
8
|
|
9
|
-
it '
|
9
|
+
it 'returns an ordered array of attribute values' do
|
10
10
|
record = table.record(0)
|
11
11
|
expect(record.to_a).to eq record_0
|
12
12
|
|
@@ -80,11 +80,11 @@ RSpec.describe DBF::Record do
|
|
80
80
|
let(:table) { DBF::Table.new fixture('cp1251.dbf') }
|
81
81
|
let(:record) { table.find(0) }
|
82
82
|
|
83
|
-
it '
|
83
|
+
it 'automaticallies encodes to default system encoding' do
|
84
84
|
expect(record.name.encoding).to eq Encoding.default_external
|
85
85
|
|
86
86
|
# russian a
|
87
|
-
expect(record.name.encode('UTF-8').
|
87
|
+
expect(record.name.encode('UTF-8').unpack1('H4')).to eq 'd0b0'
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
@@ -92,11 +92,11 @@ RSpec.describe DBF::Record do
|
|
92
92
|
let(:table) { DBF::Table.new fixture('cp1251.dbf'), nil, 'cp866' }
|
93
93
|
let(:record) { table.find(0) }
|
94
94
|
|
95
|
-
it '
|
95
|
+
it 'transcodes from manually specified encoding to default system encoding' do
|
96
96
|
expect(record.name.encoding).to eq Encoding.default_external
|
97
97
|
|
98
98
|
# russian а encoded in cp1251 and read as if it was encoded in cp866
|
99
|
-
expect(record.name.encode('UTF-8').
|
99
|
+
expect(record.name.encode('UTF-8').unpack1('H4')).to eq 'd180'
|
100
100
|
end
|
101
101
|
end
|
102
102
|
end
|
data/spec/dbf/table_spec.rb
CHANGED
@@ -83,12 +83,12 @@ RSpec.describe DBF::Table do
|
|
83
83
|
end
|
84
84
|
|
85
85
|
describe '#sequel_schema' do
|
86
|
-
it '
|
86
|
+
it 'returns a valid Sequel migration by default' do
|
87
87
|
control_schema = File.read(fixture('dbase_83_schema_sq.txt'))
|
88
88
|
expect(table.sequel_schema).to eq control_schema
|
89
89
|
end
|
90
90
|
|
91
|
-
it '
|
91
|
+
it 'returns a limited Sequel migration when passed true' do
|
92
92
|
control_schema = File.read(fixture('dbase_83_schema_sq_lim.txt'))
|
93
93
|
expect(table.sequel_schema).to eq control_schema
|
94
94
|
end
|
@@ -132,7 +132,7 @@ RSpec.describe DBF::Table do
|
|
132
132
|
begin
|
133
133
|
$stdout = StringIO.new
|
134
134
|
table.to_csv
|
135
|
-
expect($stdout.string).
|
135
|
+
expect($stdout.string).to_not be_empty
|
136
136
|
ensure
|
137
137
|
$stdout = STDOUT
|
138
138
|
end
|
@@ -143,7 +143,7 @@ RSpec.describe DBF::Table do
|
|
143
143
|
before { table.to_csv('test.csv') }
|
144
144
|
|
145
145
|
it 'creates a custom csv file' do
|
146
|
-
expect(File.
|
146
|
+
expect(File).to be_exist('test.csv')
|
147
147
|
end
|
148
148
|
end
|
149
149
|
end
|
@@ -156,7 +156,7 @@ RSpec.describe DBF::Table do
|
|
156
156
|
end
|
157
157
|
|
158
158
|
describe '#current_record' do
|
159
|
-
it '
|
159
|
+
it 'returns nil for deleted records' do
|
160
160
|
allow(table).to receive(:deleted_record?).and_return(true)
|
161
161
|
expect(table.record(0)).to be_nil
|
162
162
|
end
|
@@ -201,24 +201,24 @@ RSpec.describe DBF::Table do
|
|
201
201
|
expect(table.find(:all, 'WEIGHT' => 0.0)).to eq table.select { |r| r['weight'] == 0.0 }
|
202
202
|
end
|
203
203
|
|
204
|
-
it '
|
204
|
+
it 'ANDS multiple search terms' do
|
205
205
|
expect(table.find(:all, 'ID' => 30, :IMAGE => 'graphics/00000001/TBC01.jpg')).to be_empty
|
206
206
|
end
|
207
207
|
|
208
|
-
it '
|
209
|
-
expect(table.find(:all, 'WEIGHT' => 0.0)).
|
208
|
+
it 'matches original column names' do
|
209
|
+
expect(table.find(:all, 'WEIGHT' => 0.0)).to_not be_empty
|
210
210
|
end
|
211
211
|
|
212
212
|
it 'matches symbolized column names' do
|
213
|
-
expect(table.find(:all, :
|
213
|
+
expect(table.find(:all, WEIGHT: 0.0)).to_not be_empty
|
214
214
|
end
|
215
215
|
|
216
216
|
it 'matches downcased column names' do
|
217
|
-
expect(table.find(:all, 'weight' => 0.0)).
|
217
|
+
expect(table.find(:all, 'weight' => 0.0)).to_not be_empty
|
218
218
|
end
|
219
219
|
|
220
220
|
it 'matches symbolized downcased column names' do
|
221
|
-
expect(table.find(:all, :
|
221
|
+
expect(table.find(:all, weight: 0.0)).to_not be_empty
|
222
222
|
end
|
223
223
|
end
|
224
224
|
|
@@ -276,13 +276,13 @@ RSpec.describe DBF::Table do
|
|
276
276
|
let(:table) { DBF::Table.new fixture('dbase_03.dbf') }
|
277
277
|
|
278
278
|
it 'is false' do
|
279
|
-
expect(table
|
279
|
+
expect(table).to_not have_memo_file
|
280
280
|
end
|
281
281
|
end
|
282
282
|
|
283
283
|
describe 'with a memo file' do
|
284
284
|
it 'is true' do
|
285
|
-
expect(table
|
285
|
+
expect(table).to have_memo_file
|
286
286
|
end
|
287
287
|
end
|
288
288
|
end
|
@@ -293,7 +293,7 @@ RSpec.describe DBF::Table do
|
|
293
293
|
it 'is an array of Columns' do
|
294
294
|
expect(columns).to be_an(Array)
|
295
295
|
expect(columns).to_not be_empty
|
296
|
-
expect(columns.
|
296
|
+
expect(columns).to be_all { |c| c.class == DBF::Column }
|
297
297
|
end
|
298
298
|
end
|
299
299
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dbf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Keith Morrison
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-01-05 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A small fast library for reading dBase, xBase, Clipper and FoxPro database
|
14
14
|
files.
|
@@ -111,8 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
111
111
|
- !ruby/object:Gem::Version
|
112
112
|
version: 1.3.0
|
113
113
|
requirements: []
|
114
|
-
|
115
|
-
rubygems_version: 2.7.6
|
114
|
+
rubygems_version: 3.0.2
|
116
115
|
signing_key:
|
117
116
|
specification_version: 4
|
118
117
|
summary: Read xBase files
|