csv2hash 0.1.1 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4090ad5c8ae287a7993eaa7dd625fb7afbd3e550
4
- data.tar.gz: 005e9fade78e3197a82bc90e22239447b678544a
3
+ metadata.gz: 8e9db6b93dc1699a3757bb2e9d813285c58e5f4b
4
+ data.tar.gz: aa03c5a3d6679ac7b1598052dbe8cb38a9ea88ae
5
5
  SHA512:
6
- metadata.gz: 6451cd53411bbcb95227fba3a24d3022b89e2d739564065a4d4de9aba9b9de341940a21f5437f4700991c011d5cba85ac4e924e4707d0c0bd6baca793c6680d6
7
- data.tar.gz: 70e8675bf35dfa087805d02ac8cd370e1ab8598f8e5763b901b37a578ca7571b3029657fcdf9c8abffaf83c54d6bea5baa6bce595b105f4fe9e1a067f0841a16
6
+ metadata.gz: d3aa7cdba3548a4bca5e185ee550fbf3812b0912fd5f0a47b4db131a3245a4e736bfb89a93dbd259118cdd37b405a6958fdf4a58d6e07b1ceab208d69436d232
7
+ data.tar.gz: 9485aca4d1047db6566e07b8dd87282c505fe4db9ad5d7cd4db6f5b8097819b50aeeea0c381a2beca64ec1e096938713a04f674c973d80a5995fbd5dc49f9d4a
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- csv2hash (0.1.1)
4
+ csv2hash (0.2.0)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
data/README.md CHANGED
@@ -120,7 +120,7 @@ Precise position validation sample:
120
120
  end
121
121
 
122
122
  def definition
123
- Csv2Hash::Definition.new(rules, type = Csv2Hash::Definition::MAPPING, 1)
123
+ Csv2Hash::Definition.new(rules, type = Csv2Hash::Definition::MAPPING, header_size: 1)
124
124
  end
125
125
 
126
126
  end
@@ -159,11 +159,45 @@ Collection validation sample:
159
159
  end
160
160
 
161
161
  def definition
162
- Csv2Hash::Definition.new(rules, type = Csv2Hash::Definition::MAPPING, 1)
162
+ Csv2Hash::Definition.new(rules, type = Csv2Hash::Definition::COLLECTION, header_size: 1)
163
163
  end
164
164
 
165
165
  end
166
166
 
167
+
168
+ ### Structure validation rules
169
+
170
+ You may want to validate some structure, like min or max number of columns, definition accepts structure_rules as a key for the third parameter.
171
+ Current validations are: MinColumn, MaxColumn
172
+
173
+ class MyParser
174
+
175
+ attr_accessor :file_path
176
+
177
+ def initialize file_path
178
+ @file_path = file_path
179
+ end
180
+
181
+ def data
182
+ @data_wrapper ||= Csv2hash.new(definition, file_path).parse
183
+ end
184
+
185
+ private
186
+
187
+ def rules
188
+ [].tap do |mapping|
189
+ mapping << { position: 0, key: 'nickname' }
190
+ mapping << { position: 1, key: 'first_name' }
191
+ mapping << { position: 2, key: 'last_name' }
192
+ end
193
+ end
194
+
195
+ def definition
196
+ Csv2Hash::Definition.new(rules, type = Csv2Hash::Definition::COLLECTION, structure_rules: {'MinColumn' => 2, 'MaxColumn' => 3})
197
+ end
198
+ end
199
+
200
+
167
201
  ### CSV Headers
168
202
 
169
203
  You can define the number of rows to skip in the header of the CSV.
@@ -275,9 +309,22 @@ Csv data
275
309
  [ [ 'Foo' ] ]
276
310
 
277
311
 
278
- ### Limitations
312
+ ### Upgrading from 0.1 to 0.2
313
+
314
+ The signature of Definition#initialize changed, as last parameter is a configuration hash, while in versions prior to 0.2 it was an integer (header_size) consider upgrading your code :
315
+
316
+ Prior to 0.2 :
317
+
318
+ ```
319
+ Csv2Hash::Definition.new(rules, type = Csv2Hash::Definition::COLLECTION, 1)
320
+ ```
321
+
322
+ Starting from 0.2 :
323
+ ```
324
+ Csv2Hash::Definition.new(rules, type = Csv2Hash::Definition::COLLECTION, header_size: 1)
325
+ ```
279
326
 
280
- * Don't manage number of column you expected on collection mode
327
+ If no configuration is passed, header_size defaults remains to 0
281
328
 
282
329
  ## Contributing
283
330
 
data/ReleaseNotes.md CHANGED
@@ -1,3 +1,8 @@
1
+ VERSION 0.2
2
+
3
+ * The signature of Definition#new
4
+ * Add checking of number of columns
5
+
1
6
  VERSION 0.1
2
7
 
3
8
  * Add csv errors mode
data/csv2hash.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |spec|
2
2
 
3
3
  spec.name = 'csv2hash'
4
- spec.version = '0.1.1'
4
+ spec.version = '0.2.0'
5
5
  spec.date = '2013-11-26'
6
6
  spec.summary = %q{Mapping a CSV to a Ruby Hash}
7
7
  spec.description = %q{DSL to map a CSV to a Ruby Hash}
@@ -6,10 +6,11 @@ class Csv2hash
6
6
 
7
7
  TYPES = [MAPPING, COLLECTION]
8
8
 
9
- attr_accessor :rules, :type, :header_size
9
+ attr_accessor :rules, :type, :header_size, :structure_rules
10
10
 
11
- def initialize rules, type, header_size=0
12
- self.rules, self.type, self.header_size = rules, type, header_size
11
+ def initialize rules, type, options = {}
12
+ self.rules, self.type = rules, type
13
+ self.header_size, self.structure_rules = options.fetch(:header_size) { 0 }, options.fetch(:structure_rules) { {} }
13
14
  end
14
15
 
15
16
  def validate!
@@ -17,6 +18,7 @@ class Csv2hash
17
18
  raise "not suitable type, please use '#{MAPPING}' or '#{COLLECTION}'"
18
19
  end
19
20
  raise 'rules must be an Array of rules' unless rules.class == Array
21
+ raise 'structure rules must be a Hash of rules' unless structure_rules.class == Hash
20
22
  end
21
23
 
22
24
  def default!
@@ -0,0 +1,18 @@
1
+ module Csv2hash::StructureValidator
2
+ class MaxColumns
3
+
4
+ include Csv2hash::StructureValidator::Validator
5
+
6
+ def initialize max_size
7
+ @max_size = max_size
8
+ end
9
+
10
+ def validate_line line
11
+ line.size > @max_size
12
+ end
13
+
14
+ def error_message line
15
+ "Too many columns (max. #{@max_size}) on line #{line}"
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ module Csv2hash::StructureValidator
2
+ class MinColumns
3
+
4
+ include Csv2hash::StructureValidator::Validator
5
+
6
+ def initialize min_size
7
+ @min_size = min_size
8
+ end
9
+
10
+ def validate_line line
11
+ line.size < @min_size
12
+ end
13
+
14
+ def error_message line
15
+ "Not enough columns (min. #{@min_size}) on line #{line}"
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,27 @@
1
+ module Csv2hash::StructureValidator
2
+ class ValidationError < StandardError ; end
3
+
4
+ def validate_structure!
5
+ definition.structure_rules.each do |rule, options|
6
+ begin
7
+ rule_instance(rule, options).validate! data_source
8
+ rescue => e
9
+ self.errors << e.message
10
+ raise if exception_mode
11
+ end
12
+ end
13
+
14
+ def rule_instance rule, options
15
+ Csv2hash::StructureValidator.const_get(rule).new(options)
16
+ end
17
+ end
18
+
19
+ module Validator
20
+ def validate! source
21
+ source.index { |line| validate_line line }.tap do |line|
22
+ raise Csv2hash::StructureValidator::ValidationError, error_message(line) unless line.nil?
23
+ end
24
+ true
25
+ end
26
+ end
27
+ end
@@ -1,3 +1,3 @@
1
1
  module Cvs2hash
2
- VERSION = '0.1.1'
2
+ VERSION = '0.2.0'
3
3
  end
data/lib/csv2hash.rb CHANGED
@@ -3,6 +3,9 @@ require 'csv2hash/definition'
3
3
  require 'csv2hash/validator'
4
4
  require 'csv2hash/validator/mapping'
5
5
  require 'csv2hash/validator/collection'
6
+ require 'csv2hash/structure_validator'
7
+ require 'csv2hash/structure_validator/max_columns'
8
+ require 'csv2hash/structure_validator/min_columns'
6
9
  require 'csv2hash/parser'
7
10
  require 'csv2hash/parser/mapping'
8
11
  require 'csv2hash/parser/collection'
@@ -15,6 +18,8 @@ require 'csv'
15
18
 
16
19
  class Csv2hash
17
20
 
21
+ include Csv2hash::StructureValidator
22
+
18
23
  attr_accessor :definition, :file_path, :data, :notifier, :exception_mode, :errors, :ignore_blank_line
19
24
 
20
25
  def initialize definition, file_path, exception_mode=true, data_source=nil, ignore_blank_line=false
@@ -26,6 +31,7 @@ class Csv2hash
26
31
  self.notifier = Notifier.new
27
32
  self.ignore_blank_line = ignore_blank_line
28
33
  init_plugins
34
+
29
35
  end
30
36
 
31
37
  def init_plugins
@@ -42,6 +48,7 @@ class Csv2hash
42
48
 
43
49
  definition.validate!
44
50
  definition.default!
51
+ validate_structure!
45
52
  validate_data!
46
53
 
47
54
  Csv2hash::DataWrapper.new.tap do |response|
@@ -2,10 +2,11 @@ require 'spec_helper'
2
2
 
3
3
  describe Csv2hash::Definition do
4
4
 
5
+ let(:valid_rules) { [ { position: [0,0], key: 'name' } ] }
5
6
  context 'regular context' do
6
7
  subject do
7
8
  Csv2hash::Definition.new(
8
- [ { position: [0,0], key: 'name' } ],
9
+ valid_rules,
9
10
  Csv2hash::Definition::MAPPING
10
11
  )
11
12
  end
@@ -36,6 +37,15 @@ describe Csv2hash::Definition do
36
37
  expect { subject.validate! }.to raise_error 'rules must be an Array of rules'
37
38
  end
38
39
  end
40
+
41
+ context 'structure rules failling validation' do
42
+ subject do
43
+ Csv2hash::Definition.new valid_rules, Csv2hash::Definition::MAPPING, { structure_rules: 'invalid structure rule' }
44
+ end
45
+ it 'should throw exception' do
46
+ expect { subject.validate! }.to raise_error 'structure rules must be a Hash of rules'
47
+ end
48
+ end
39
49
  end
40
50
 
41
51
  describe '#default!' do
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ describe Csv2hash::StructureValidator do
4
+
5
+ let(:rules) { [ { position: [0,0], key: 'name' } ] }
6
+ let(:options) { {} }
7
+ let(:definition) do
8
+ Csv2hash::Definition.new(rules, Csv2hash::Definition::MAPPING, options).tap do |definition|
9
+ definition.validate!
10
+ definition.default!
11
+ end
12
+ end
13
+
14
+ subject do
15
+ Csv2hash.new(definition, 'file_path', true, data_source)
16
+ end
17
+
18
+ context '#MaxColumns' do
19
+ let(:options){ { structure_rules: { 'MaxColumns' => 2 } } }
20
+
21
+ context 'valid data' do
22
+ let(:data_source) do
23
+ [
24
+ [ 'John', 'Doe' ]
25
+ ]
26
+ end
27
+ it { expect { subject.validate_structure! }.to_not raise_error }
28
+ end
29
+
30
+ context 'invalid data' do
31
+ let(:data_source) do
32
+ [
33
+ [ 'John', 'Doe' ],
34
+ [ 'Jane', 'Doe', 'extra field' ]
35
+ ]
36
+ end
37
+ it { expect { subject.validate_structure! }.to raise_error 'Too many columns (max. 2) on line 1' }
38
+ end
39
+ end
40
+
41
+ context '#MinColumns' do
42
+ let(:options){ { structure_rules: { 'MinColumns' => 2 } } }
43
+
44
+ context 'valid data' do
45
+ let(:data_source) do
46
+ [
47
+ [ 'John', 'Doe', 'foo' ]
48
+ ]
49
+ end
50
+ it { expect { subject.validate_structure! }.to_not raise_error }
51
+ end
52
+
53
+ context 'invalid data' do
54
+ let(:data_source) do
55
+ [
56
+ [ 'John' ],
57
+ [ 'Jane', 'Doe' ]
58
+ ]
59
+ end
60
+ it { expect { subject.validate_structure! }.to raise_error 'Not enough columns (min. 2) on line 0' }
61
+ end
62
+ end
63
+
64
+ end
@@ -1,9 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Csv2hash::Validator::Collection do
4
-
4
+ let(:options) { {} }
5
5
  let(:definition) do
6
- Csv2hash::Definition.new([ { position: 0, key: 'name' } ], Csv2hash::Definition::COLLECTION).tap do |definition|
6
+ Csv2hash::Definition.new([ { position: 0, key: 'name' } ], Csv2hash::Definition::COLLECTION, options).tap do |definition|
7
7
  definition.validate!
8
8
  definition.default!
9
9
  end
@@ -17,7 +17,7 @@ describe Csv2hash::Validator::Collection do
17
17
  let(:data_source) { [ [ 'John Doe' ] ]}
18
18
  it { expect { subject.validate_data! }.to_not raise_error }
19
19
  context 'with header' do
20
- before { subject.definition.header_size = 1 }
20
+ let(:options) { { header_size: 1 } }
21
21
  let(:data_source) { [ [ 'Name' ], [ 'John Doe' ] ]}
22
22
  it { expect { subject.validate_data! }.to_not raise_error }
23
23
  end
@@ -37,7 +37,7 @@ describe Csv2hash::Validator::Collection do
37
37
  let(:data_source) { [ [ ] ] }
38
38
  it { expect { subject.validate_data! }.to raise_error('undefined name on [0, 0]') }
39
39
  context 'with header' do
40
- before { subject.definition.header_size = 1 }
40
+ let(:options) { { header_size: 1 } }
41
41
  let(:data_source) { [ [ 'Name' ], [ ] ]}
42
42
  it { expect { subject.validate_data! }.to raise_error('undefined name on [1, 0]') }
43
43
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: csv2hash
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel AZEMAR
@@ -83,6 +83,9 @@ files:
83
83
  - lib/csv2hash/parser.rb
84
84
  - lib/csv2hash/parser/collection.rb
85
85
  - lib/csv2hash/parser/mapping.rb
86
+ - lib/csv2hash/structure_validator.rb
87
+ - lib/csv2hash/structure_validator/max_columns.rb
88
+ - lib/csv2hash/structure_validator/min_columns.rb
86
89
  - lib/csv2hash/validator.rb
87
90
  - lib/csv2hash/validator/collection.rb
88
91
  - lib/csv2hash/validator/mapping.rb
@@ -91,6 +94,7 @@ files:
91
94
  - spec/csv2hash/parser/collection_spec.rb
92
95
  - spec/csv2hash/parser/mapping_spec.rb
93
96
  - spec/csv2hash/parser_spec.rb
97
+ - spec/csv2hash/structure_validator_spec.rb
94
98
  - spec/csv2hash/validator/collection_spec.rb
95
99
  - spec/csv2hash/validator/mapping_spec.rb
96
100
  - spec/csv2hash/validator_spec.rb
@@ -125,6 +129,7 @@ test_files:
125
129
  - spec/csv2hash/parser/collection_spec.rb
126
130
  - spec/csv2hash/parser/mapping_spec.rb
127
131
  - spec/csv2hash/parser_spec.rb
132
+ - spec/csv2hash/structure_validator_spec.rb
128
133
  - spec/csv2hash/validator/collection_spec.rb
129
134
  - spec/csv2hash/validator/mapping_spec.rb
130
135
  - spec/csv2hash/validator_spec.rb