dbf 1.6.7 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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