iron-import 0.5.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 +7 -0
- data/.rspec +1 -0
- data/History.txt +12 -0
- data/LICENSE +20 -0
- data/README.rdoc +70 -0
- data/Version.txt +1 -0
- data/lib/iron/import/column.rb +177 -0
- data/lib/iron/import/csv_reader.rb +26 -0
- data/lib/iron/import/data_reader.rb +176 -0
- data/lib/iron/import/error.rb +66 -0
- data/lib/iron/import/importer.rb +188 -0
- data/lib/iron/import/row.rb +59 -0
- data/lib/iron/import/sheet.rb +186 -0
- data/lib/iron/import/xls_reader.rb +60 -0
- data/lib/iron/import/xlsx_reader.rb +60 -0
- data/lib/iron/import.rb +14 -0
- data/spec/importer/column_spec.rb +116 -0
- data/spec/importer/csv_reader_spec.rb +31 -0
- data/spec/importer/data_reader_spec.rb +93 -0
- data/spec/importer/importer_spec.rb +28 -0
- data/spec/importer/row_spec.rb +37 -0
- data/spec/importer/sheet_spec.rb +65 -0
- data/spec/importer/xlsx_reader_spec.rb +35 -0
- data/spec/samples/nanodrop.xlsx +0 -0
- data/spec/samples/simple.csv +4 -0
- data/spec/samples/test-products.xls +0 -0
- data/spec/spec_helper.rb +21 -0
- metadata +128 -0
@@ -0,0 +1,93 @@
|
|
1
|
+
describe Importer::DataReader do
|
2
|
+
|
3
|
+
before do
|
4
|
+
@importer = Importer.new
|
5
|
+
@reader = Importer::DataReader.new(@importer, :test)
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should parse integers' do
|
9
|
+
{
|
10
|
+
'1234' => 1234,
|
11
|
+
'-2' => -2,
|
12
|
+
'5.00' => 5,
|
13
|
+
'foo' => nil,
|
14
|
+
'' => nil,
|
15
|
+
55 => 55,
|
16
|
+
3.0 => 3
|
17
|
+
}.each_pair do |val, res|
|
18
|
+
@reader.parse_value(val, :integer).should == res
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should parse floats' do
|
23
|
+
{
|
24
|
+
'1.256' => 1.256,
|
25
|
+
'-20.3' => -20.3,
|
26
|
+
'5.00' => 5.0,
|
27
|
+
'foo' => nil,
|
28
|
+
'' => nil,
|
29
|
+
55 => 55.0,
|
30
|
+
'3' => 3.0
|
31
|
+
}.each_pair do |val, res|
|
32
|
+
@reader.parse_value(val, :float).should == res
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should parse strings' do
|
37
|
+
{
|
38
|
+
'blah' => 'blah',
|
39
|
+
" spaces \t" => 'spaces',
|
40
|
+
'' => nil,
|
41
|
+
255 => '255',
|
42
|
+
-1.5 => '-1.5'
|
43
|
+
}.each_pair do |val, res|
|
44
|
+
@reader.parse_value(val, :string).should == res
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should parse cents' do
|
49
|
+
{
|
50
|
+
'$123.00' => 12300,
|
51
|
+
'5' => 500,
|
52
|
+
'0.5' => 50,
|
53
|
+
'-95' => -9500,
|
54
|
+
52 => 5200,
|
55
|
+
1.0 => 100,
|
56
|
+
1.25 => 125
|
57
|
+
}.each_pair do |val, res|
|
58
|
+
@reader.parse_value(val, :cents).should == res
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should parse dates' do
|
63
|
+
{
|
64
|
+
'1/5/73' => Date.new(1973,1,5),
|
65
|
+
'05/30/01' => Date.new(2001,5,30),
|
66
|
+
'2005-12-10' => Date.new(2005,12,10),
|
67
|
+
'4/10/14 22:28' => Date.new(2014,4,10),
|
68
|
+
'5/10/2014, 10:28:07 PM' => Date.new(2014,5,10),
|
69
|
+
Date.new(2000,4,1) => Date.new(2000,4,1)
|
70
|
+
}.each_pair do |val, res|
|
71
|
+
@reader.parse_value(val, :date).should == res
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should build an instance based on format' do
|
76
|
+
Importer::DataReader.for_format(@importer, :csv).should be_a(Importer::CsvReader)
|
77
|
+
Importer::DataReader.for_format(@importer, :xls).should be_a(Importer::XlsReader)
|
78
|
+
Importer::DataReader.for_format(@importer, :xlsx).should be_a(Importer::XlsxReader)
|
79
|
+
Importer::DataReader.for_format(@importer, :foo).should be_nil
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should build an instance based on a path' do
|
83
|
+
Importer::DataReader.for_path(@importer, '/tmp/foo.csv').should be_a(Importer::CsvReader)
|
84
|
+
Importer::DataReader.for_path(@importer, 'BAR.XLS').should be_a(Importer::XlsReader)
|
85
|
+
Importer::DataReader.for_path(@importer, '/tmp/nog_bog.xlsx').should be_a(Importer::XlsxReader)
|
86
|
+
Importer::DataReader.for_path(@importer, '/tmp/blinkin.bmp').should be_nil
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should build an instance based on stream' do
|
90
|
+
Importer::DataReader.for_stream(@importer, mock(original_filename: "nanodrop.xlsx", content_type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")).should be_a(Importer::XlsxReader)
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
describe Importer do
|
2
|
+
|
3
|
+
it 'should respond to build' do
|
4
|
+
Importer.should respond_to(:build)
|
5
|
+
end
|
6
|
+
|
7
|
+
it 'should import a test csv file' do
|
8
|
+
importer = Importer.build do
|
9
|
+
column :number
|
10
|
+
column :string
|
11
|
+
column :date
|
12
|
+
column :cost
|
13
|
+
end
|
14
|
+
importer.import(SpecHelper.sample_path('simple.csv')).should be_true
|
15
|
+
count = 0
|
16
|
+
found = false
|
17
|
+
importer.process do |row|
|
18
|
+
count += 1
|
19
|
+
if row.line == 4
|
20
|
+
found = true
|
21
|
+
row[:date].should == '2004-02-01'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
found.should be_true
|
25
|
+
count.should == 3
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
describe Importer::Row do
|
2
|
+
|
3
|
+
before do
|
4
|
+
@importer = Importer.new
|
5
|
+
@sheet = @importer.default_sheet
|
6
|
+
@row = Importer::Row.new(@sheet, 5)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should store and retrieve values' do
|
10
|
+
@row.set_values(:a => 1, :b => 2)
|
11
|
+
@row.values.should == {:a => 1, :b => 2}
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should allow [] access' do
|
15
|
+
@row.set_values(:a => 1, :b => 2)
|
16
|
+
@row[:b].should == 2
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should test for value presence in all columns' do
|
20
|
+
@row.set_values(:a => 1, :b => 2)
|
21
|
+
@row.should be_all
|
22
|
+
@row.set_values(:a => 1, :b => nil)
|
23
|
+
@row.should_not be_all
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should test for specific value\'s presence' do
|
27
|
+
@row.set_values(:a => 1, :b => 2, :c => nil)
|
28
|
+
@row.all?(:a, :b).should be_true
|
29
|
+
@row.all?(:c).should be_false
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should be empty? with zero values' do
|
33
|
+
@row.set_values(:a => nil, :b => nil)
|
34
|
+
@row.should be_empty
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
describe Importer::Sheet do
|
2
|
+
|
3
|
+
before do
|
4
|
+
@importer = Importer.new
|
5
|
+
@sheet = @importer.default_sheet
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should respond to build' do
|
9
|
+
@sheet.should respond_to(:build)
|
10
|
+
@sheet.build do
|
11
|
+
column :foo
|
12
|
+
end
|
13
|
+
@sheet.columns.count.should == 1
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should define columns' do
|
17
|
+
@sheet.column(:foo)
|
18
|
+
@sheet.columns.count.should == 1
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should find headers automatically' do
|
22
|
+
# Define a few sample columns
|
23
|
+
@sheet.column(:alpha)
|
24
|
+
@sheet.column(:gamma)
|
25
|
+
# Some dummy data
|
26
|
+
rows = [
|
27
|
+
['', '', '', ''],
|
28
|
+
['Alpha', 'Beta', 'Gamma', 'Epsilon']
|
29
|
+
]
|
30
|
+
|
31
|
+
# Parse it!
|
32
|
+
@sheet.parse_header(rows).should be_true
|
33
|
+
|
34
|
+
@sheet.column(:alpha).data.index.should == 0
|
35
|
+
@sheet.column(:gamma).data.index.should == 2
|
36
|
+
@sheet.data.start_row.should == 3
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should record an error if a column can\'t be found' do
|
40
|
+
# Define a few sample columns
|
41
|
+
@sheet.column(:alpha)
|
42
|
+
@sheet.column(:gamma)
|
43
|
+
# Some dummy data
|
44
|
+
rows = [
|
45
|
+
['', '', '', ''],
|
46
|
+
['Bob', 'Beta', 'Gamma', 'Epsilon']
|
47
|
+
]
|
48
|
+
|
49
|
+
# Parse it!
|
50
|
+
@sheet.parse_header(rows).should be_false
|
51
|
+
@importer.errors.count.should == 1
|
52
|
+
@importer.error_summary.should =~ /unable to locate required column header/i
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should match by sheet name or number' do
|
56
|
+
@sheet.id = 5
|
57
|
+
@sheet.match_sheet?('foo', 3).should be_false
|
58
|
+
@sheet.match_sheet?('foo', 4).should be_true
|
59
|
+
|
60
|
+
@sheet.id = 'Sheet 5'
|
61
|
+
@sheet.match_sheet?('Sheet', 4).should be_false
|
62
|
+
@sheet.match_sheet?('Sheet 5', 3).should be_true
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
describe Importer::XlsxReader do
|
2
|
+
|
3
|
+
it 'should load our nanodrop data' do
|
4
|
+
importer = Importer.build do
|
5
|
+
column :sample_id do
|
6
|
+
required!
|
7
|
+
validate do |val|
|
8
|
+
raise 'Invalid ID' unless val.match(/[0-9]{3,}\.[0-9]\z/)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
column :a260 do
|
12
|
+
type :float
|
13
|
+
end
|
14
|
+
column :a280 do
|
15
|
+
type :float
|
16
|
+
end
|
17
|
+
column :factor do
|
18
|
+
type :integer
|
19
|
+
end
|
20
|
+
|
21
|
+
# Skip empty rows
|
22
|
+
filter do |row|
|
23
|
+
row.all?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
res = importer.import(SpecHelper.sample_path('nanodrop.xlsx'))
|
27
|
+
importer.error_summary.should be_nil
|
28
|
+
res.should be_true
|
29
|
+
importer.default_sheet.dump.should == [
|
30
|
+
{:sample_id => 'Windsor_buccal_500.1', :a260 => 2.574, :a280 => 1.277, :factor => 50},
|
31
|
+
{:sample_id => 'Weston_fecal_206.2', :a260 => 0.746, :a280 => 0.351, :factor => 50}
|
32
|
+
]
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
Binary file
|
Binary file
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Set up development requirements
|
2
|
+
require 'roo'
|
3
|
+
|
4
|
+
# Require our library
|
5
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'iron', 'import'))
|
6
|
+
|
7
|
+
# Config RSpec options
|
8
|
+
RSpec.configure do |config|
|
9
|
+
config.color = true
|
10
|
+
config.add_formatter 'documentation'
|
11
|
+
config.backtrace_exclusion_patterns = [/rspec/]
|
12
|
+
end
|
13
|
+
|
14
|
+
module SpecHelper
|
15
|
+
|
16
|
+
# Helper to find sample file paths
|
17
|
+
def self.sample_path(file)
|
18
|
+
File.expand_path(File.join(File.dirname(__FILE__), 'samples', file))
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: iron-import
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Rob Morris
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-03-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: iron-extensions
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.2.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.2.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: iron-dsl
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.6'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.6'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: roo
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.13'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.13'
|
69
|
+
description: Simple yet powerful library for importing tabular data including support
|
70
|
+
for auto-detecting column order, parsing/validating cell data, aggregating errors,
|
71
|
+
etc.
|
72
|
+
email:
|
73
|
+
- rob@irongaze.com
|
74
|
+
executables: []
|
75
|
+
extensions: []
|
76
|
+
extra_rdoc_files: []
|
77
|
+
files:
|
78
|
+
- ".rspec"
|
79
|
+
- History.txt
|
80
|
+
- LICENSE
|
81
|
+
- README.rdoc
|
82
|
+
- Version.txt
|
83
|
+
- lib/iron/import.rb
|
84
|
+
- lib/iron/import/column.rb
|
85
|
+
- lib/iron/import/csv_reader.rb
|
86
|
+
- lib/iron/import/data_reader.rb
|
87
|
+
- lib/iron/import/error.rb
|
88
|
+
- lib/iron/import/importer.rb
|
89
|
+
- lib/iron/import/row.rb
|
90
|
+
- lib/iron/import/sheet.rb
|
91
|
+
- lib/iron/import/xls_reader.rb
|
92
|
+
- lib/iron/import/xlsx_reader.rb
|
93
|
+
- spec/importer/column_spec.rb
|
94
|
+
- spec/importer/csv_reader_spec.rb
|
95
|
+
- spec/importer/data_reader_spec.rb
|
96
|
+
- spec/importer/importer_spec.rb
|
97
|
+
- spec/importer/row_spec.rb
|
98
|
+
- spec/importer/sheet_spec.rb
|
99
|
+
- spec/importer/xlsx_reader_spec.rb
|
100
|
+
- spec/samples/nanodrop.xlsx
|
101
|
+
- spec/samples/simple.csv
|
102
|
+
- spec/samples/test-products.xls
|
103
|
+
- spec/spec_helper.rb
|
104
|
+
homepage: http://irongaze.com
|
105
|
+
licenses:
|
106
|
+
- MIT
|
107
|
+
metadata: {}
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
require_paths:
|
111
|
+
- lib
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: 1.9.2
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
requirements: []
|
123
|
+
rubyforge_project:
|
124
|
+
rubygems_version: 2.4.3
|
125
|
+
signing_key:
|
126
|
+
specification_version: 4
|
127
|
+
summary: CSV, XLS, and XLSX import automation support
|
128
|
+
test_files: []
|