rcsvreader 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/lib/csv_reader.rb +87 -0
  2. data/test/data/foo.csv +5 -0
  3. data/test/test.rb +77 -0
  4. metadata +65 -0
data/lib/csv_reader.rb ADDED
@@ -0,0 +1,87 @@
1
+ require 'rubygems'
2
+ require 'ccsv'
3
+
4
+ # Copyright (c) 2010, Daniel Quirino Oliveira
5
+ # All rights reserved.
6
+ #
7
+ # Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
11
+ # * Neither the name of the owner nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
12
+ #
13
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
+
15
+ module CSV
16
+
17
+ class CSVReader
18
+
19
+ def initialize(file, expected_header)
20
+ @file = file
21
+ check_header(expected_header)
22
+ @expected_header = expected_header
23
+ end
24
+
25
+ # Iterates through the CSV file
26
+ def foreach
27
+ row_num = 0
28
+ Ccsv.foreach(@file) do |r|
29
+ yield parse_row(r) unless row_num == 0 #skips the header
30
+ row_num += 1
31
+ end
32
+ end
33
+
34
+ # Retrieves the column names from CSV header
35
+ def header
36
+ if @header == nil
37
+ Ccsv.foreach(@file) do |line|
38
+ @header = line
39
+ break
40
+ end
41
+ end
42
+ return @header
43
+ end
44
+
45
+ def check_header(expected_header)
46
+ curr_header = header
47
+ if (expected_header.empty?)
48
+ raise InvalidHeaderException, "Expected header cannot be empty."
49
+ end
50
+ if (curr_header.size < expected_header.size ||
51
+ (curr_header & expected_header).empty?)
52
+ raise InvalidHeaderException, "Expected header #{expected_header} does not match or is not contained in the current header #{curr_header}."
53
+ end
54
+ end
55
+
56
+ # Parses each row of the CSV file into a hash
57
+ # Hash:
58
+ # |Column1|Value1|
59
+ # |Column2|Value2|
60
+ # . .
61
+ # . .
62
+ # |ColumnN|ValueN|
63
+ #
64
+ # Column1-N represents a column as described in CSV header.
65
+ # Values1-N represents a value for each row of the CSV file directly bound to the Nth column.
66
+ def parse_row(r)
67
+ row = {}
68
+ i = 0
69
+ @expected_header.each do |column|
70
+ row[column] = r[header.index(column)]
71
+ i += 1
72
+ end
73
+ return row
74
+ end
75
+
76
+ private :parse_row, :header, :check_header
77
+
78
+ end
79
+
80
+ class InvalidHeaderException < RuntimeError
81
+ attr_reader :message
82
+
83
+ def initialize(message)
84
+ @message = message
85
+ end
86
+ end
87
+ end
data/test/data/foo.csv ADDED
@@ -0,0 +1,5 @@
1
+ name,email
2
+ Daniel Quirino Oliveira,danielqo@gmail.com
3
+ John Doe,doe@email.com
4
+ ,anon@noemail.com
5
+ Sem Email,
data/test/test.rb ADDED
@@ -0,0 +1,77 @@
1
+ require 'test/unit'
2
+ require '../lib/csv_reader.rb'
3
+
4
+ # Copyright (c) 2010, Daniel Quirino Oliveira
5
+ # All rights reserved.
6
+ #
7
+ # Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
11
+ # * Neither the name of the owner nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
12
+ #
13
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
+
15
+ class TestCSVReader < Test::Unit::TestCase
16
+
17
+ def setup
18
+ @data_dir = "#{File.dirname(__FILE__)}/data/"
19
+ end
20
+
21
+ def test_fetch_all_rows_and_all_columns_sorted
22
+ reader = CSV::CSVReader.new("#{@data_dir}/foo.csv", ["name","email"])
23
+ expected_lines = 4
24
+ lines = 0
25
+ reader.foreach do |line|
26
+ lines += 1
27
+ end
28
+ assert_equal expected_lines, lines
29
+ end
30
+
31
+ def test_fetch_all_rows_and_all_columns_unsorted
32
+ reader = CSV::CSVReader.new("#{@data_dir}/foo.csv", ["email","name"])
33
+ expected_lines = 4
34
+ lines = 0
35
+ reader.foreach do |line|
36
+ lines += 1
37
+ end
38
+ assert_equal expected_lines, lines
39
+ end
40
+
41
+ def test_fetch_all_rows_and_only_expected_columns
42
+ reader = CSV::CSVReader.new("#{@data_dir}/foo.csv", ["email"])
43
+ expected_lines = 4
44
+ lines = 0
45
+ reader.foreach do |line|
46
+ lines += 1
47
+ end
48
+ assert_equal expected_lines, lines
49
+ end
50
+
51
+ def test_accept_partial_valid_header
52
+ assert_nothing_raised do
53
+ reader = CSV::CSVReader.new("#{@data_dir}/foo.csv", ["name"])
54
+ end
55
+ end
56
+
57
+ def test_fail_missing_age_column_in_csv_header
58
+ assert_raise CSV::InvalidHeaderException do
59
+ reader = CSV::CSVReader.new("#{@data_dir}/foo.csv", ["name", "email", "age"])
60
+ end
61
+ end
62
+
63
+ def test_fail_invalid_header
64
+ assert_raise CSV::InvalidHeaderException do
65
+ reader = CSV::CSVReader.new("#{@data_dir}/foo.csv", ["foo","bar"])
66
+ end
67
+ end
68
+
69
+ def test_fail_no_expected_header
70
+ assert_raise CSV::InvalidHeaderException do
71
+ reader = CSV::CSVReader.new("#{@data_dir}/foo.csv", [])
72
+ end
73
+ end
74
+
75
+
76
+
77
+ end
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rcsvreader
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - Daniel Quirino Oliveira
8
+ autorequire: name
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-07 00:00:00 -02:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: ccsv
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - "="
22
+ - !ruby/object:Gem::Version
23
+ version: "0.1"
24
+ version:
25
+ description:
26
+ email: daniel@nullability.org
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files: []
32
+
33
+ files:
34
+ - lib/csv_reader.rb
35
+ has_rdoc: true
36
+ homepage: http://github.com/danielqo/rcsvreader
37
+ licenses: []
38
+
39
+ post_install_message:
40
+ rdoc_options: []
41
+
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ version:
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ requirements: []
57
+
58
+ rubyforge_project:
59
+ rubygems_version: 1.3.5
60
+ signing_key:
61
+ specification_version: 3
62
+ summary: Yet another CSV parser with CSV header validation, based on CCSV (http://github.com/fauna/ccsv/).
63
+ test_files:
64
+ - test/data/foo.csv
65
+ - test/test.rb