smarter_csv 1.1.5 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +6 -0
- data/lib/smarter_csv/smarter_csv.rb +19 -2
- data/lib/smarter_csv/version.rb +1 -1
- data/spec/fixtures/duplicate_headers.csv +3 -0
- data/spec/fixtures/user_import.csv +3 -0
- data/spec/smarter_csv/invalid_headers_spec.rb +52 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 251eb1eff306211d163c6be6880ba45e3eb29985
|
4
|
+
data.tar.gz: 9e16d1d4aaab86df7a65d73e6a23ace8f481ba4e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e2ad758ddb7d644777df1b9f38b73c7c4c0753d76507834bf68e86394ae017b1f5caa16867efd82f4c0443d4a7c1b4c1d7f704d9c3796e71083bde689ee7aeba
|
7
|
+
data.tar.gz: 8f7126500628a17fda587a05678aca9140d0ebb7ca168fc3144b1d9c00d2be6ec901a43900bd3d558aceb0a8dcfc139aba7347e6dbad01b2ff83c19dc3816763
|
data/README.md
CHANGED
@@ -193,6 +193,8 @@ The options and the block are optional.
|
|
193
193
|
| :chunk_size | nil | if set, determines the desired chunk-size (defaults to nil, no chunk processing) |
|
194
194
|
---------------------------------------------------------------------------------------------------------------------------------
|
195
195
|
| :key_mapping | nil | a hash which maps headers from the CSV file to keys in the result hash |
|
196
|
+
| :required_headers | nil | An array. Eacn of the given headers must be present in the CSV file, |
|
197
|
+
| | | or an exception is raised No validation if nil is given. |
|
196
198
|
| :remove_unmapped_keys | false | when using :key_mapping option, should non-mapped keys / columns be removed? |
|
197
199
|
| :downcase_header | true | downcase all column headers |
|
198
200
|
| :strings_as_keys | false | use strings instead of symbols as the keys in the result hashes |
|
@@ -293,6 +295,10 @@ Planned in the next releases:
|
|
293
295
|
|
294
296
|
## Changes
|
295
297
|
|
298
|
+
#### 1.2.0 (2018-01-20)
|
299
|
+
* add default validation that a header can only appear once
|
300
|
+
* add option `required_headers`
|
301
|
+
|
296
302
|
#### 1.1.5 (2017-11-05)
|
297
303
|
* fix issue with invalid byte sequences in header (issue #103, thanks to Dave Myron)
|
298
304
|
* fix issue with invalid byte sequences in multi-line data (thanks to Ivan Ushakov)
|
@@ -1,8 +1,10 @@
|
|
1
1
|
module SmarterCSV
|
2
2
|
|
3
3
|
class HeaderSizeMismatch < Exception; end
|
4
|
-
|
5
4
|
class IncorrectOption < Exception; end
|
5
|
+
class DuplicateHeaders < Exception; end
|
6
|
+
class MissingHeaders < Exception; end
|
7
|
+
|
6
8
|
|
7
9
|
def SmarterCSV.process(input, options={}, &block) # first parameter: filename or input object with readline method
|
8
10
|
default_options = {:col_sep => ',' , :row_sep => $/ , :quote_char => '"', :force_simple_split => false , :verbose => false ,
|
@@ -10,7 +12,7 @@ module SmarterCSV
|
|
10
12
|
:convert_values_to_numeric => true, :strip_chars_from_headers => nil , :user_provided_headers => nil , :headers_in_file => true,
|
11
13
|
:comment_regexp => /^#/, :chunk_size => nil , :key_mapping_hash => nil , :downcase_header => true, :strings_as_keys => false, :file_encoding => 'utf-8',
|
12
14
|
:remove_unmapped_keys => false, :keep_original_headers => false, :value_converters => nil, :skip_lines => nil, :force_utf8 => false, :invalid_byte_sequence => '',
|
13
|
-
:auto_row_sep_chars => 500
|
15
|
+
:auto_row_sep_chars => 500, :required_headers => nil
|
14
16
|
}
|
15
17
|
options = default_options.merge(options)
|
16
18
|
options[:invalid_byte_sequence] = '' if options[:invalid_byte_sequence].nil?
|
@@ -93,6 +95,21 @@ module SmarterCSV
|
|
93
95
|
end
|
94
96
|
end
|
95
97
|
|
98
|
+
# header_validations
|
99
|
+
duplicate_headers = []
|
100
|
+
headerA.compact.each do |k|
|
101
|
+
duplicate_headers << k if headerA.select{|x| x == k}.size > 1
|
102
|
+
end
|
103
|
+
raise SmarterCSV::DuplicateHeaders , "ERORR [smarter_csv]: duplicate headers: #{duplicate_headers.join(',')}" unless duplicate_headers.empty?
|
104
|
+
|
105
|
+
if options[:required_headers] && options[:required_headers].is_a?(Array)
|
106
|
+
missing_headers = []
|
107
|
+
options[:required_headers].each do |k|
|
108
|
+
missing_headers << k unless headerA.include?(k)
|
109
|
+
end
|
110
|
+
raise SmarterCSV::MissingHeaders , "ERORR [smarter_csv]: missing headers: #{missing_headers.join(',')}" unless missing_headers.empty?
|
111
|
+
end
|
112
|
+
|
96
113
|
# in case we use chunking.. we'll need to set it up..
|
97
114
|
if ! options[:chunk_size].nil? && options[:chunk_size].to_i > 0
|
98
115
|
use_chunks = true
|
data/lib/smarter_csv/version.rb
CHANGED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
fixture_path = 'spec/fixtures'
|
4
|
+
|
5
|
+
describe 'test exceptions for invalid headers' do
|
6
|
+
it 'raises error on duplicate headers' do
|
7
|
+
expect {
|
8
|
+
SmarterCSV.process("#{fixture_path}/duplicate_headers.csv", {})
|
9
|
+
}.to raise_exception(SmarterCSV::DuplicateHeaders)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'raises error on duplicate given headers' do
|
13
|
+
expect {
|
14
|
+
options = {:user_provided_headers => [:a,:b,:c,:d,:a]}
|
15
|
+
SmarterCSV.process("#{fixture_path}/duplicate_headers.csv", options)
|
16
|
+
}.to raise_exception(SmarterCSV::DuplicateHeaders)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'raises error on duplicate mapped headers' do
|
20
|
+
expect {
|
21
|
+
# the mapping is right, but the underlying csv file is bad
|
22
|
+
options = {:key_mapping => {:email => :a, :firstname => :b, :lastname => :c, :manager_email => :d, :age => :e} }
|
23
|
+
SmarterCSV.process("#{fixture_path}/duplicate_headers.csv", options)
|
24
|
+
}.to raise_exception(SmarterCSV::DuplicateHeaders)
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
it 'does not raise an error if no required headers are given' do
|
29
|
+
options = {:required_headers => nil} # order does not matter
|
30
|
+
data = SmarterCSV.process("#{fixture_path}/user_import.csv", options)
|
31
|
+
data.size.should eq 2
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'does not raise an error if no required headers are given' do
|
35
|
+
options = {:required_headers => []} # order does not matter
|
36
|
+
data = SmarterCSV.process("#{fixture_path}/user_import.csv", options)
|
37
|
+
data.size.should eq 2
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'does not raise an error if the required headers are present' do
|
41
|
+
options = {:required_headers => [:lastname,:email,:firstname,:manager_email]} # order does not matter
|
42
|
+
data = SmarterCSV.process("#{fixture_path}/user_import.csv", options)
|
43
|
+
data.size.should eq 2
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'raises an error if a required header is missing' do
|
47
|
+
expect {
|
48
|
+
options = {:required_headers => [:lastname,:email,:employee_id,:firstname,:manager_email]} # order does not matter
|
49
|
+
SmarterCSV.process("#{fixture_path}/user_import.csv", options)
|
50
|
+
}.to raise_exception(SmarterCSV::MissingHeaders)
|
51
|
+
end
|
52
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: smarter_csv
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- 'Tilo Sloboda
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2018-01-20 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec
|
@@ -56,6 +56,7 @@ files:
|
|
56
56
|
- spec/fixtures/carriage_returns_r.csv
|
57
57
|
- spec/fixtures/carriage_returns_rn.csv
|
58
58
|
- spec/fixtures/chunk_cornercase.csv
|
59
|
+
- spec/fixtures/duplicate_headers.csv
|
59
60
|
- spec/fixtures/empty.csv
|
60
61
|
- spec/fixtures/line_endings_n.csv
|
61
62
|
- spec/fixtures/line_endings_r.csv
|
@@ -70,6 +71,7 @@ files:
|
|
70
71
|
- spec/fixtures/quoted.csv
|
71
72
|
- spec/fixtures/separator.csv
|
72
73
|
- spec/fixtures/skip_lines.csv
|
74
|
+
- spec/fixtures/user_import.csv
|
73
75
|
- spec/fixtures/valid_unicode.csv
|
74
76
|
- spec/fixtures/with_dashes.csv
|
75
77
|
- spec/fixtures/with_dates.csv
|
@@ -82,6 +84,7 @@ files:
|
|
82
84
|
- spec/smarter_csv/convert_values_to_numeric_spec.rb
|
83
85
|
- spec/smarter_csv/extenstions_spec.rb
|
84
86
|
- spec/smarter_csv/header_transformation_spec.rb
|
87
|
+
- spec/smarter_csv/invalid_headers_spec.rb
|
85
88
|
- spec/smarter_csv/keep_headers_spec.rb
|
86
89
|
- spec/smarter_csv/key_mapping_spec.rb
|
87
90
|
- spec/smarter_csv/line_ending_spec.rb
|
@@ -138,6 +141,7 @@ test_files:
|
|
138
141
|
- spec/fixtures/carriage_returns_r.csv
|
139
142
|
- spec/fixtures/carriage_returns_rn.csv
|
140
143
|
- spec/fixtures/chunk_cornercase.csv
|
144
|
+
- spec/fixtures/duplicate_headers.csv
|
141
145
|
- spec/fixtures/empty.csv
|
142
146
|
- spec/fixtures/line_endings_n.csv
|
143
147
|
- spec/fixtures/line_endings_r.csv
|
@@ -152,6 +156,7 @@ test_files:
|
|
152
156
|
- spec/fixtures/quoted.csv
|
153
157
|
- spec/fixtures/separator.csv
|
154
158
|
- spec/fixtures/skip_lines.csv
|
159
|
+
- spec/fixtures/user_import.csv
|
155
160
|
- spec/fixtures/valid_unicode.csv
|
156
161
|
- spec/fixtures/with_dashes.csv
|
157
162
|
- spec/fixtures/with_dates.csv
|
@@ -164,6 +169,7 @@ test_files:
|
|
164
169
|
- spec/smarter_csv/convert_values_to_numeric_spec.rb
|
165
170
|
- spec/smarter_csv/extenstions_spec.rb
|
166
171
|
- spec/smarter_csv/header_transformation_spec.rb
|
172
|
+
- spec/smarter_csv/invalid_headers_spec.rb
|
167
173
|
- spec/smarter_csv/keep_headers_spec.rb
|
168
174
|
- spec/smarter_csv/key_mapping_spec.rb
|
169
175
|
- spec/smarter_csv/line_ending_spec.rb
|