dbf 1.6.7 → 1.7.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.
@@ -1,3 +1,7 @@
1
+ # 1.7.0
2
+ - allow DBF::Table to work with dbf data in memory
3
+ - allow DBF::Table#to_csv to write to STDOUT
4
+
1
5
  # 1.6.7
2
6
  - memo columns return nil when no memo file found
3
7
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dbf (1.6.6)
4
+ dbf (1.7.0)
5
5
  fastercsv (~> 1.5.4)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -104,7 +104,7 @@ Create an executable ActiveRecord schema:
104
104
 
105
105
  Dump all records to a CSV file:
106
106
 
107
- dbf -c books.dbf
107
+ dbf -c books.dbf > books.csv
108
108
 
109
109
  ## dBase version support
110
110
 
data/lib/dbf.rb CHANGED
@@ -11,5 +11,5 @@ require 'dbf/attributes'
11
11
  require 'dbf/record'
12
12
  require 'dbf/column'
13
13
  require 'dbf/foxpro_column'
14
- require 'dbf/memo'
15
- require 'dbf/table'
14
+ require 'dbf/table'
15
+ require 'dbf/memo'
@@ -2,6 +2,7 @@ module DBF
2
2
  class Memo
3
3
  BLOCK_HEADER_SIZE = 8
4
4
  FPT_HEADER_SIZE = 512
5
+ FPT_FORMAT_VERSIONS = DBF::Table::FOXPRO_VERSIONS.keys
5
6
 
6
7
  def self.open(filename, version)
7
8
  self.new File.open(filename, 'rb'), version
@@ -12,7 +13,7 @@ module DBF
12
13
  end
13
14
 
14
15
  def format
15
- File.extname(@data.path)
16
+ format_fpt? ? 'fpt' : 'dbt'
16
17
  end
17
18
 
18
19
  def get(start_block)
@@ -32,7 +33,7 @@ module DBF
32
33
  private
33
34
 
34
35
  def format_fpt? #nodoc
35
- File.extname(@data.path) =~ /fpt/i
36
+ FPT_FORMAT_VERSIONS.include?(@version)
36
37
  end
37
38
 
38
39
  def build_fpt_memo(start_block) #nodoc
@@ -29,14 +29,25 @@ module DBF
29
29
  attr_accessor :encoding # Source encoding (for ex. :cp1251)
30
30
 
31
31
  # Opens a DBF::Table
32
- # Example:
32
+ # Examples:
33
+ # # working with a file stored on the filesystem
33
34
  # table = DBF::Table.new 'data.dbf'
34
35
  #
35
- # @param [String] path Path to the dbf file
36
- def initialize(path)
37
- @data = File.open(path, 'rb')
36
+ # # working with a misnamed memo file
37
+ # table = DBF::Table.new 'data.dbf', 'memo.dbt'
38
+ #
39
+ # # working with a dbf in memory
40
+ # table = DBF::Table.new StringIO.new(dbf_data)
41
+ #
42
+ # # working with a dbf and memo in memory
43
+ # table = DBF::Table.new StringIO.new(dbf_data), StringIO.new(memo_data)
44
+ #
45
+ # @param [String, StringIO] data Path to the dbf file or a StringIO object
46
+ # @param [optional String, StringIO] memo Path to the memo file or a StringIO object
47
+ def initialize(data, memo = nil)
48
+ @data = open_data(data)
38
49
  get_header_info
39
- @memo = open_memo(path)
50
+ @memo = open_memo(data, memo)
40
51
  end
41
52
 
42
53
  # @return [TrueClass, FalseClass]
@@ -121,12 +132,11 @@ module DBF
121
132
  # Dumps all records to a CSV file. If no filename is given then CSV is
122
133
  # output to STDOUT.
123
134
  #
124
- # @param [optional String] path Defaults to basename of dbf file
135
+ # @param [optional String] path Defaults to STDOUT
125
136
  def to_csv(path = nil)
126
- csv_class.open(path || default_csv_path, 'w', :force_quotes => true) do |csv|
127
- csv << columns.map {|c| c.name}
128
- each {|record| csv << record.to_a}
129
- end
137
+ csv = csv_class.new((path ? File.open(path, 'w') : $stdout), :force_quotes => true)
138
+ csv << columns.map {|c| c.name}
139
+ each {|record| csv << record.to_a}
130
140
  end
131
141
 
132
142
  # Find records using a simple ActiveRecord-like syntax.
@@ -199,11 +209,23 @@ module DBF
199
209
  @column_count ||= (@header_length - DBF_HEADER_SIZE + 1) / DBF_HEADER_SIZE
200
210
  end
201
211
 
202
- def open_memo(path) #nodoc
203
- dirname = File.dirname(path)
204
- basename = File.basename(path, '.*')
205
- files = Dir.glob("#{dirname}/#{basename}*.{fpt,FPT,dbt,DBT}")
206
- files.any? ? Memo.open(files.first, version) : nil
212
+ def open_data(data)
213
+ data.is_a?(StringIO) ? data : File.open(data, 'rb')
214
+ end
215
+
216
+ def open_memo(data, memo = nil) #nodoc
217
+ if memo.is_a? StringIO
218
+ DBF::Memo.new(memo, version)
219
+ elsif memo
220
+ DBF::Memo.open(memo, version)
221
+ elsif !data.is_a? StringIO
222
+ dirname = File.dirname(data)
223
+ basename = File.basename(data, '.*')
224
+ files = Dir.glob("#{dirname}/#{basename}*.{fpt,FPT,dbt,DBT}")
225
+ files.any? ? DBF::Memo.open(files.first, version) : nil
226
+ else
227
+ nil
228
+ end
207
229
  end
208
230
 
209
231
  def find_all(options) #nodoc
@@ -238,10 +260,6 @@ module DBF
238
260
  CSV.const_defined?(:Reader) ? FCSV : CSV
239
261
  end
240
262
 
241
- def default_csv_path #nodoc
242
- File.basename(@data.path, '.dbf') + '.csv'
243
- end
244
-
245
263
  def self.encodings #nodoc
246
264
  @encodings ||= YAML.load_file File.expand_path("../encodings.yml", __FILE__)
247
265
  end
@@ -1,3 +1,3 @@
1
1
  module DBF
2
- VERSION = '1.6.7'
2
+ VERSION = '1.7.0'
3
3
  end
@@ -4,6 +4,27 @@ describe DBF::Table do
4
4
  specify 'foxpro versions' do
5
5
  DBF::Table::FOXPRO_VERSIONS.keys.should == %w(30 31 f5 fb)
6
6
  end
7
+
8
+ describe '#initialize' do
9
+ it 'should accept a DBF filename' do
10
+ expect { DBF::Table.new "#{DB_PATH}/dbase_83.dbf" }.to_not raise_error
11
+ end
12
+
13
+ it 'should accept a DBF and Memo filename' do
14
+ expect { DBF::Table.new "#{DB_PATH}/dbase_83.dbf", "#{DB_PATH}/dbase_83.dbt" }.to_not raise_error
15
+ end
16
+
17
+ it 'should accept an io-like data object' do
18
+ data = StringIO.new File.read("#{DB_PATH}/dbase_83.dbf")
19
+ expect { DBF::Table.new data }.to_not raise_error
20
+ end
21
+
22
+ it 'should accept an io-like data and memo object' do
23
+ data = StringIO.new File.read("#{DB_PATH}/dbase_83.dbf")
24
+ memo = StringIO.new File.read("#{DB_PATH}/dbase_83.dbt")
25
+ expect { DBF::Table.new data, memo }.to_not raise_error
26
+ end
27
+ end
7
28
 
8
29
  context "when closed" do
9
30
  before do
@@ -32,13 +53,19 @@ describe DBF::Table do
32
53
  let(:table) { DBF::Table.new "#{DB_PATH}/dbase_83.dbf" }
33
54
 
34
55
  after do
35
- FileUtils.rm_f 'dbase_83.csv'
36
56
  FileUtils.rm_f 'test.csv'
37
57
  end
38
58
 
39
- it 'should create default dump.csv' do
40
- table.to_csv
41
- File.exists?('dbase_83.csv').should be_true
59
+ describe 'when no path param passed' do
60
+ it 'should dump to STDOUT' do
61
+ begin
62
+ $stdout = StringIO.new
63
+ table.to_csv
64
+ $stdout.string.should_not be_empty
65
+ ensure
66
+ $stdout = STDOUT
67
+ end
68
+ end
42
69
  end
43
70
 
44
71
  describe 'when path param passed' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dbf
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.7
4
+ version: 1.7.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-23 00:00:00.000000000Z
12
+ date: 2011-12-09 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fastercsv
16
- requirement: &70198302238320 !ruby/object:Gem::Requirement
16
+ requirement: &70246163177540 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 1.5.4
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70198302238320
24
+ version_requirements: *70246163177540
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &70198302237860 !ruby/object:Gem::Requirement
27
+ requirement: &70246163177080 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 2.7.0
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70198302237860
35
+ version_requirements: *70246163177080
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rake
38
- requirement: &70198302237300 !ruby/object:Gem::Requirement
38
+ requirement: &70246163176620 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 0.9.2
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70198302237300
46
+ version_requirements: *70246163176620
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rdoc
49
- requirement: &70198302236780 !ruby/object:Gem::Requirement
49
+ requirement: &70246163176160 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 3.9.0
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70198302236780
57
+ version_requirements: *70246163176160
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: ruby-debug19
60
- requirement: &70198302236340 !ruby/object:Gem::Requirement
60
+ requirement: &70246163175760 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,7 +65,7 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70198302236340
68
+ version_requirements: *70246163175760
69
69
  description: A small fast library for reading dBase, xBase, Clipper and FoxPro database
70
70
  files.
71
71
  email: keithm@infused.org