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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 042aadb2bc5426a07a64f09e781bccbd728e8052
4
- data.tar.gz: ba48c2e303591d4027e05d1208c225381d362857
3
+ metadata.gz: 251eb1eff306211d163c6be6880ba45e3eb29985
4
+ data.tar.gz: 9e16d1d4aaab86df7a65d73e6a23ace8f481ba4e
5
5
  SHA512:
6
- metadata.gz: 58cb92edabb46bdcb48598d4b4b02b5f0f09cc63378e818ac672daf8d722b5fbf1b246df5db262dff306e87943a2bb2bebbb753944adc5449b19cd5a1475c00b
7
- data.tar.gz: 31fe30f2b2027274a5252c55b234b120327be6ce652f7ad71232bd8a920e33d30cbae42577fff398d0a61574dc17b3016cd3fa1d520eec3dd4636569cc62860e
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
@@ -1,3 +1,3 @@
1
1
  module SmarterCSV
2
- VERSION = "1.1.5"
2
+ VERSION = "1.2.0"
3
3
  end
@@ -0,0 +1,3 @@
1
+ email,firstname,lastname,email,age
2
+ tom@bla.com,Tom,Sawyer,mike@bla.com,34
3
+ eri@bla.com,Eri Chan,tom@bla.com,21
@@ -0,0 +1,3 @@
1
+ email,firstname,lastname,manager_email,department
2
+ tom@bla.com,Tom,Sawyer,mike@bla.com,IT
3
+ eri@bla.com,Eri Chan,tom@bla.com,IT
@@ -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.1.5
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: 2017-11-06 00:00:00.000000000 Z
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