fastercsv 0.1.4 → 0.1.6
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.
- data/CHANGELOG +16 -0
- data/Rakefile +1 -1
- data/TODO +0 -5
- data/lib/faster_csv.rb +655 -40
- data/test/tc_csv_parsing.rb +2 -2
- data/test/tc_data_converters.rb +166 -0
- data/test/tc_features.rb +18 -0
- data/test/tc_headers.rb +125 -0
- data/test/tc_interface.rb +28 -0
- data/test/tc_row.rb +264 -0
- data/test/ts_all.rb +3 -0
- metadata +41 -35
data/test/tc_csv_parsing.rb
CHANGED
@@ -110,8 +110,8 @@ class TestCSVParsing < Test::Unit::TestCase
|
|
110
110
|
end
|
111
111
|
|
112
112
|
def test_malformed_csv
|
113
|
-
assert_raise(FasterCSV::MalformedCSVError) do
|
114
|
-
FasterCSV.parse_line("1,2\r,3")
|
113
|
+
assert_raise(FasterCSV::MalformedCSVError) do
|
114
|
+
FasterCSV.parse_line("1,2\r,3", :row_sep => "\n")
|
115
115
|
end
|
116
116
|
|
117
117
|
assert_raise(FasterCSV::MalformedCSVError) do
|
@@ -0,0 +1,166 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
# tc_data_converters.rb
|
4
|
+
#
|
5
|
+
# Created by James Edward Gray II on 2005-12-30.
|
6
|
+
# Copyright 2005 Gray Productions. All rights reserved.
|
7
|
+
|
8
|
+
require "test/unit"
|
9
|
+
|
10
|
+
require "faster_csv"
|
11
|
+
|
12
|
+
class TestDataConverters < Test::Unit::TestCase
|
13
|
+
def setup
|
14
|
+
@data = "Numbers,:integer,1,:float,3.015"
|
15
|
+
@parser = FasterCSV.new(@data)
|
16
|
+
|
17
|
+
@custom = lambda { |field| field =~ /\A:(\S.*?)\s*\Z/ ? $1.to_sym : field }
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_builtin_integer_converter
|
21
|
+
# does convert
|
22
|
+
[-5, 1, 10000000000].each do |n|
|
23
|
+
assert_equal(n, FasterCSV::Converters[:integer][n.to_s])
|
24
|
+
end
|
25
|
+
|
26
|
+
# does not convert
|
27
|
+
(%w{junk 1.0} + [""]).each do |str|
|
28
|
+
assert_equal(str, FasterCSV::Converters[:integer][str])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_builtin_float_converter
|
33
|
+
# does convert
|
34
|
+
[-5.1234, 0, 2.3e-11].each do |n|
|
35
|
+
assert_equal(n, FasterCSV::Converters[:float][n.to_s])
|
36
|
+
end
|
37
|
+
|
38
|
+
# does not convert
|
39
|
+
(%w{junk 1..0 .015F} + [""]).each do |str|
|
40
|
+
assert_equal(str, FasterCSV::Converters[:float][str])
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_builtin_date_converter
|
45
|
+
# does convert
|
46
|
+
assert_instance_of(Date, FasterCSV::Converters[:date][Time.now.to_s])
|
47
|
+
|
48
|
+
# does not convert
|
49
|
+
assert_instance_of(String, FasterCSV::Converters[:date]["junk"])
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_builtin_date_time_converter
|
53
|
+
# does convert
|
54
|
+
assert_instance_of( DateTime,
|
55
|
+
FasterCSV::Converters[:date_time][Time.now.to_s] )
|
56
|
+
|
57
|
+
# does not convert
|
58
|
+
assert_instance_of(String, FasterCSV::Converters[:date_time]["junk"])
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_convert_with_builtin
|
62
|
+
# setup parser...
|
63
|
+
assert(@parser.respond_to?(:convert))
|
64
|
+
assert_nothing_raised(Exception) { @parser.convert(:integer) }
|
65
|
+
|
66
|
+
# and use
|
67
|
+
assert_equal(["Numbers", ":integer", 1, ":float", "3.015"], @parser.shift)
|
68
|
+
|
69
|
+
setup # reset
|
70
|
+
|
71
|
+
# setup parser...
|
72
|
+
assert_nothing_raised(Exception) { @parser.convert(:float) }
|
73
|
+
|
74
|
+
# and use
|
75
|
+
assert_equal(["Numbers", ":integer", 1.0, ":float", 3.015], @parser.shift)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_convert_order
|
79
|
+
# floats first, then integers...
|
80
|
+
assert_nothing_raised(Exception) do
|
81
|
+
@parser.convert(:float)
|
82
|
+
@parser.convert(:integer)
|
83
|
+
end
|
84
|
+
|
85
|
+
# gets us nothing but floats
|
86
|
+
assert_equal( [String, String, Float, String, Float],
|
87
|
+
@parser.shift.map { |field| field.class } )
|
88
|
+
|
89
|
+
setup # reset
|
90
|
+
|
91
|
+
# integers have precendance...
|
92
|
+
assert_nothing_raised(Exception) do
|
93
|
+
@parser.convert(:integer)
|
94
|
+
@parser.convert(:float)
|
95
|
+
end
|
96
|
+
|
97
|
+
# gives us proper number conversion
|
98
|
+
assert_equal( [String, String, Fixnum, String, Float],
|
99
|
+
@parser.shift.map { |field| field.class } )
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_builtin_numeric_combo_converter
|
103
|
+
# setup parser...
|
104
|
+
assert_nothing_raised(Exception) { @parser.convert(:numeric) }
|
105
|
+
|
106
|
+
# and use
|
107
|
+
assert_equal( [String, String, Fixnum, String, Float],
|
108
|
+
@parser.shift.map { |field| field.class } )
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_builtin_all_nested_combo_converter
|
112
|
+
# setup parser...
|
113
|
+
@data << ",#{Time.now}" # add a DateTime field
|
114
|
+
@parser = FasterCSV.new(@data) # reset parser
|
115
|
+
assert_nothing_raised(Exception) { @parser.convert(:all) }
|
116
|
+
|
117
|
+
# and use
|
118
|
+
assert_equal( [String, String, Fixnum, String, Float, DateTime],
|
119
|
+
@parser.shift.map { |field| field.class } )
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_convert_with_custom_code
|
123
|
+
# define custom converter...
|
124
|
+
assert_nothing_raised(Exception) do
|
125
|
+
@parser.convert { |field| field =~ /\A:(\S.*?)\s*\Z/ ? $1.to_sym : field }
|
126
|
+
end
|
127
|
+
|
128
|
+
# and use
|
129
|
+
assert_equal(["Numbers", :integer, "1", :float, "3.015"], @parser.shift)
|
130
|
+
|
131
|
+
setup # reset
|
132
|
+
|
133
|
+
# mix built-in and custom...
|
134
|
+
assert_nothing_raised(Exception) { @parser.convert(:numeric) }
|
135
|
+
assert_nothing_raised(Exception) { @parser.convert(&@custom) }
|
136
|
+
|
137
|
+
# and use
|
138
|
+
assert_equal(["Numbers", :integer, 1, :float, 3.015], @parser.shift)
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_convert_with_custom_code_using_field_info
|
142
|
+
# define custom converter that uses field information...
|
143
|
+
assert_nothing_raised(Exception) do
|
144
|
+
@parser.convert do |field, info|
|
145
|
+
assert_equal(1, info.line)
|
146
|
+
info.index == 4 ? Float(field).floor : field
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
# and use
|
151
|
+
assert_equal(["Numbers", ":integer", "1", ":float", 3], @parser.shift)
|
152
|
+
end
|
153
|
+
|
154
|
+
def test_shortcut_interface
|
155
|
+
assert_equal( ["Numbers", ":integer", 1, ":float", 3.015],
|
156
|
+
FasterCSV.parse_line(@data, :converters => :numeric) )
|
157
|
+
|
158
|
+
assert_equal( ["Numbers", ":integer", 1, ":float", 3.015],
|
159
|
+
FasterCSV.parse_line( @data, :converters => [ :integer,
|
160
|
+
:float ] ) )
|
161
|
+
|
162
|
+
assert_equal( ["Numbers", :integer, 1, :float, 3.015],
|
163
|
+
FasterCSV.parse_line( @data, :converters => [ :numeric,
|
164
|
+
@custom ] ) )
|
165
|
+
end
|
166
|
+
end
|
data/test/tc_features.rb
CHANGED
@@ -49,6 +49,24 @@ class TestFasterCSVFeatures < Test::Unit::TestCase
|
|
49
49
|
:row_sep => "\r\n") )
|
50
50
|
end
|
51
51
|
|
52
|
+
def test_row_sep_auto_discovery
|
53
|
+
["\r\n", "\n", "\r"].each do |line_end|
|
54
|
+
data = "1,2,3#{line_end}4,5#{line_end}"
|
55
|
+
discovered = FasterCSV.new(data).instance_eval { @row_sep }
|
56
|
+
assert_equal(line_end, discovered)
|
57
|
+
end
|
58
|
+
|
59
|
+
assert_equal("\n", FasterCSV.new("\n\r\n\r").instance_eval { @row_sep })
|
60
|
+
|
61
|
+
assert_equal($/, FasterCSV.new("").instance_eval { @row_sep })
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_unknown_options
|
65
|
+
assert_raise(ArgumentError) do
|
66
|
+
FasterCSV.new(String.new, :unknown => :error)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
52
70
|
def test_bug_fixes
|
53
71
|
# failing to escape <tt>:col_sep</tt> (reported by Kev Jackson)
|
54
72
|
assert_nothing_raised(Exception) do
|
data/test/tc_headers.rb
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
# tc_headers.rb
|
4
|
+
#
|
5
|
+
# Created by James Edward Gray II on 2006-02-25.
|
6
|
+
# Copyright 2006 Gray Productions. All rights reserved.
|
7
|
+
|
8
|
+
require "test/unit"
|
9
|
+
|
10
|
+
require "faster_csv"
|
11
|
+
|
12
|
+
class TestFasterCSVHeaders < Test::Unit::TestCase
|
13
|
+
def setup
|
14
|
+
@data = <<-END_CSV.gsub(/^\s+/, "")
|
15
|
+
first,second,third
|
16
|
+
A,B,C
|
17
|
+
1,2,3
|
18
|
+
END_CSV
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_first_row
|
22
|
+
[:first_row, true].each do |setting| # two names for the same setting
|
23
|
+
# activate headers
|
24
|
+
csv = nil
|
25
|
+
assert_nothing_raised(Exception) do
|
26
|
+
csv = FasterCSV.parse(@data, :headers => setting)
|
27
|
+
end
|
28
|
+
|
29
|
+
# first data row - skipping headers
|
30
|
+
row = csv.shift
|
31
|
+
assert_not_nil(row)
|
32
|
+
assert_instance_of(FasterCSV::Row, row)
|
33
|
+
assert_equal([%w{first A}, %w{second B}, %w{third C}], row.to_a)
|
34
|
+
|
35
|
+
# second data row
|
36
|
+
row = csv.shift
|
37
|
+
assert_not_nil(row)
|
38
|
+
assert_instance_of(FasterCSV::Row, row)
|
39
|
+
assert_equal([%w{first 1}, %w{second 2}, %w{third 3}], row.to_a)
|
40
|
+
|
41
|
+
# empty
|
42
|
+
assert_nil(csv.shift)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_return_headers
|
47
|
+
# activate headers and request they are returned
|
48
|
+
csv = nil
|
49
|
+
assert_nothing_raised(Exception) do
|
50
|
+
csv = FasterCSV.parse(@data, :headers => true, :return_headers => true)
|
51
|
+
end
|
52
|
+
|
53
|
+
# header row
|
54
|
+
row = csv.shift
|
55
|
+
assert_not_nil(row)
|
56
|
+
assert_instance_of(FasterCSV::Row, row)
|
57
|
+
assert_equal( [%w{first first}, %w{second second}, %w{third third}],
|
58
|
+
row.to_a )
|
59
|
+
|
60
|
+
# first data row - skipping headers
|
61
|
+
row = csv.shift
|
62
|
+
assert_not_nil(row)
|
63
|
+
assert_instance_of(FasterCSV::Row, row)
|
64
|
+
assert_equal([%w{first A}, %w{second B}, %w{third C}], row.to_a)
|
65
|
+
|
66
|
+
# second data row
|
67
|
+
row = csv.shift
|
68
|
+
assert_not_nil(row)
|
69
|
+
assert_instance_of(FasterCSV::Row, row)
|
70
|
+
assert_equal([%w{first 1}, %w{second 2}, %w{third 3}], row.to_a)
|
71
|
+
|
72
|
+
# empty
|
73
|
+
assert_nil(csv.shift)
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_converters
|
77
|
+
# create test data where headers and fields look alike
|
78
|
+
data = <<-END_MATCHING_CSV.gsub(/^\s+/, "")
|
79
|
+
1,2,3
|
80
|
+
1,2,3
|
81
|
+
END_MATCHING_CSV
|
82
|
+
|
83
|
+
# normal converters do not affect headers
|
84
|
+
csv = FasterCSV.parse( data, :headers => true,
|
85
|
+
:return_headers => true,
|
86
|
+
:converters => :numeric )
|
87
|
+
assert_equal([%w{1 1}, %w{2 2}, %w{3 3}], csv.shift.to_a)
|
88
|
+
assert_equal([["1", 1], ["2", 2], ["3", 3]], csv.shift.to_a)
|
89
|
+
assert_nil(csv.shift)
|
90
|
+
|
91
|
+
# header converters do affect headers (only)
|
92
|
+
assert_nothing_raised(Exception) do
|
93
|
+
csv = FasterCSV.parse( data, :headers => true,
|
94
|
+
:return_headers => true,
|
95
|
+
:converters => :numeric,
|
96
|
+
:header_converters => :symbol )
|
97
|
+
end
|
98
|
+
assert_equal([[:"1", :"1"], [:"2", :"2"], [:"3", :"3"]], csv.shift.to_a)
|
99
|
+
assert_equal([[:"1", 1], [:"2", 2], [:"3", 3]], csv.shift.to_a)
|
100
|
+
assert_nil(csv.shift)
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_builtin_downcase_converter
|
104
|
+
csv = FasterCSV.parse( "One,TWO Three", :headers => true,
|
105
|
+
:return_headers => true,
|
106
|
+
:header_converters => :downcase )
|
107
|
+
assert_equal(%w{one two\ three}, csv.shift.headers)
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_builtin_symbol_converter
|
111
|
+
csv = FasterCSV.parse( "One,TWO Three", :headers => true,
|
112
|
+
:return_headers => true,
|
113
|
+
:header_converters => :symbol )
|
114
|
+
assert_equal([:one, :two_three], csv.shift.headers)
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_custom_converter
|
118
|
+
converter = lambda { |header| header.tr(" ", "_") }
|
119
|
+
csv = FasterCSV.parse( "One,TWO Three",
|
120
|
+
:headers => true,
|
121
|
+
:return_headers => true,
|
122
|
+
:header_converters => converter )
|
123
|
+
assert_equal(%w{One TWO_Three}, csv.shift.headers)
|
124
|
+
end
|
125
|
+
end
|
data/test/tc_interface.rb
CHANGED
@@ -64,6 +64,12 @@ class TestFasterCSVInterface < Test::Unit::TestCase
|
|
64
64
|
assert_not_nil(row)
|
65
65
|
assert_instance_of(Array, row)
|
66
66
|
assert_equal(%w{1 2 3}, row)
|
67
|
+
|
68
|
+
# shortcut interface
|
69
|
+
row = "1;2;3".parse_csv(:col_sep => ";")
|
70
|
+
assert_not_nil(row)
|
71
|
+
assert_instance_of(Array, row)
|
72
|
+
assert_equal(%w{1 2 3}, row)
|
67
73
|
end
|
68
74
|
|
69
75
|
def test_read_and_readlines
|
@@ -115,6 +121,12 @@ class TestFasterCSVInterface < Test::Unit::TestCase
|
|
115
121
|
assert_not_nil(line)
|
116
122
|
assert_instance_of(String, line)
|
117
123
|
assert_equal("1;2;3\n", line)
|
124
|
+
|
125
|
+
# shortcut interface
|
126
|
+
line = %w{1 2 3}.to_csv(:col_sep => ";")
|
127
|
+
assert_not_nil(line)
|
128
|
+
assert_instance_of(String, line)
|
129
|
+
assert_equal("1;2;3\n", line)
|
118
130
|
end
|
119
131
|
|
120
132
|
def test_append # aliased add_row() and puts()
|
@@ -126,4 +138,20 @@ class TestFasterCSVInterface < Test::Unit::TestCase
|
|
126
138
|
|
127
139
|
test_shift
|
128
140
|
end
|
141
|
+
|
142
|
+
### Test Read and Write Interface ###
|
143
|
+
|
144
|
+
def test_filter
|
145
|
+
assert_respond_to(FasterCSV, :filter)
|
146
|
+
|
147
|
+
expected = [[1, 2, 3], [4, 5]]
|
148
|
+
FasterCSV.filter( "1;2;3\n4;5\n", (result = String.new),
|
149
|
+
:in_col_sep => ";", :out_col_sep => ",",
|
150
|
+
:converters => :all ) do |row|
|
151
|
+
assert_equal(row, expected.shift)
|
152
|
+
row.map! { |n| n * 2 }
|
153
|
+
row << "Added\r"
|
154
|
+
end
|
155
|
+
assert_equal("2,4,6,\"Added\r\"\n8,10,\"Added\r\"\n", result)
|
156
|
+
end
|
129
157
|
end
|
data/test/tc_row.rb
ADDED
@@ -0,0 +1,264 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
# tc_row.rb
|
4
|
+
#
|
5
|
+
# Created by James Edward Gray II on 2006-02-24.
|
6
|
+
# Copyright 2006 Gray Productions. All rights reserved.
|
7
|
+
|
8
|
+
require "test/unit"
|
9
|
+
|
10
|
+
require "faster_csv"
|
11
|
+
|
12
|
+
class TestFasterCSVRow < Test::Unit::TestCase
|
13
|
+
def setup
|
14
|
+
@row = FasterCSV::Row.new(%w{A B C A A}, [1, 2, 3, 4])
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_initialize
|
18
|
+
# basic
|
19
|
+
row = FasterCSV::Row.new(%w{A B C}, [1, 2, 3])
|
20
|
+
assert_not_nil(row)
|
21
|
+
assert_instance_of(FasterCSV::Row, row)
|
22
|
+
assert_equal([["A", 1], ["B", 2], ["C", 3]], row.to_a)
|
23
|
+
|
24
|
+
# missing headers
|
25
|
+
row = FasterCSV::Row.new(%w{A}, [1, 2, 3])
|
26
|
+
assert_not_nil(row)
|
27
|
+
assert_instance_of(FasterCSV::Row, row)
|
28
|
+
assert_equal([["A", 1], [nil, 2], [nil, 3]], row.to_a)
|
29
|
+
|
30
|
+
# missing fields
|
31
|
+
row = FasterCSV::Row.new(%w{A B C}, [1, 2])
|
32
|
+
assert_not_nil(row)
|
33
|
+
assert_instance_of(FasterCSV::Row, row)
|
34
|
+
assert_equal([["A", 1], ["B", 2], ["C", nil]], row.to_a)
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_headers
|
38
|
+
assert_equal(%w{A B C A A}, @row.headers)
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_field
|
42
|
+
# by name
|
43
|
+
assert_equal(2, @row.field("B"))
|
44
|
+
assert_equal(2, @row["B"]) # alias
|
45
|
+
|
46
|
+
# by index
|
47
|
+
assert_equal(3, @row.field(2))
|
48
|
+
|
49
|
+
# missing
|
50
|
+
assert_nil(@row.field("Missing"))
|
51
|
+
assert_nil(@row.field(10))
|
52
|
+
|
53
|
+
# minimum index
|
54
|
+
assert_equal(1, @row.field("A"))
|
55
|
+
assert_equal(1, @row.field("A", 0))
|
56
|
+
assert_equal(4, @row.field("A", 1))
|
57
|
+
assert_equal(4, @row.field("A", 2))
|
58
|
+
assert_equal(4, @row.field("A", 3))
|
59
|
+
assert_equal(nil, @row.field("A", 4))
|
60
|
+
assert_equal(nil, @row.field("A", 5))
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_set_field
|
64
|
+
# set field by name
|
65
|
+
assert_equal(100, @row["A"] = 100)
|
66
|
+
|
67
|
+
# set field by index
|
68
|
+
assert_equal(300, @row[3] = 300)
|
69
|
+
|
70
|
+
# set field by name and minimum index
|
71
|
+
assert_equal([:a, :b, :c], @row["A", 4] = [:a, :b, :c])
|
72
|
+
|
73
|
+
# verify the changes
|
74
|
+
assert_equal( [ ["A", 100],
|
75
|
+
["B", 2],
|
76
|
+
["C", 3],
|
77
|
+
["A", 300],
|
78
|
+
["A", [:a, :b, :c]] ], @row.to_a )
|
79
|
+
|
80
|
+
# assigning an index past the end
|
81
|
+
assert_equal("End", @row[10] = "End")
|
82
|
+
assert_equal( [ ["A", 100],
|
83
|
+
["B", 2],
|
84
|
+
["C", 3],
|
85
|
+
["A", 300],
|
86
|
+
["A", [:a, :b, :c]],
|
87
|
+
[nil, nil],
|
88
|
+
[nil, nil],
|
89
|
+
[nil, nil],
|
90
|
+
[nil, nil],
|
91
|
+
[nil, nil],
|
92
|
+
[nil, "End"] ], @row.to_a )
|
93
|
+
|
94
|
+
# assigning a new field by header
|
95
|
+
assert_equal("New", @row[:new] = "New")
|
96
|
+
assert_equal( [ ["A", 100],
|
97
|
+
["B", 2],
|
98
|
+
["C", 3],
|
99
|
+
["A", 300],
|
100
|
+
["A", [:a, :b, :c]],
|
101
|
+
[nil, nil],
|
102
|
+
[nil, nil],
|
103
|
+
[nil, nil],
|
104
|
+
[nil, nil],
|
105
|
+
[nil, nil],
|
106
|
+
[nil, "End"],
|
107
|
+
[:new, "New"] ], @row.to_a )
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_append
|
111
|
+
# add a value
|
112
|
+
assert_equal(@row, @row << "Value")
|
113
|
+
assert_equal( [ ["A", 1],
|
114
|
+
["B", 2],
|
115
|
+
["C", 3],
|
116
|
+
["A", 4],
|
117
|
+
["A", nil],
|
118
|
+
[nil, "Value"] ], @row.to_a )
|
119
|
+
|
120
|
+
# add a pair
|
121
|
+
assert_equal(@row, @row << %w{Header Field})
|
122
|
+
assert_equal( [ ["A", 1],
|
123
|
+
["B", 2],
|
124
|
+
["C", 3],
|
125
|
+
["A", 4],
|
126
|
+
["A", nil],
|
127
|
+
[nil, "Value"],
|
128
|
+
%w{Header Field} ], @row.to_a )
|
129
|
+
|
130
|
+
# a pair with Hash syntax
|
131
|
+
assert_equal(@row, @row << {:key => :value})
|
132
|
+
assert_equal( [ ["A", 1],
|
133
|
+
["B", 2],
|
134
|
+
["C", 3],
|
135
|
+
["A", 4],
|
136
|
+
["A", nil],
|
137
|
+
[nil, "Value"],
|
138
|
+
%w{Header Field},
|
139
|
+
[:key, :value] ], @row.to_a )
|
140
|
+
|
141
|
+
# multiple fields at once
|
142
|
+
assert_equal(@row, @row.push(100, 200, [:last, 300]))
|
143
|
+
assert_equal( [ ["A", 1],
|
144
|
+
["B", 2],
|
145
|
+
["C", 3],
|
146
|
+
["A", 4],
|
147
|
+
["A", nil],
|
148
|
+
[nil, "Value"],
|
149
|
+
%w{Header Field},
|
150
|
+
[:key, :value],
|
151
|
+
[nil, 100],
|
152
|
+
[nil, 200],
|
153
|
+
[:last, 300] ], @row.to_a )
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_delete
|
157
|
+
# by index
|
158
|
+
assert_equal(["B", 2], @row.delete(1))
|
159
|
+
|
160
|
+
# by header
|
161
|
+
assert_equal(["C", 3], @row.delete("C"))
|
162
|
+
|
163
|
+
# using a block
|
164
|
+
assert_equal(@row, @row.delete_if { |h, f| h == "A" and not f.nil? })
|
165
|
+
assert_equal([["A", nil]], @row.to_a)
|
166
|
+
end
|
167
|
+
|
168
|
+
def test_fields
|
169
|
+
# all fields
|
170
|
+
assert_equal([1, 2, 3, 4, nil], @row.fields)
|
171
|
+
|
172
|
+
# by header
|
173
|
+
assert_equal([1, 3], @row.fields("A", "C"))
|
174
|
+
|
175
|
+
# by index
|
176
|
+
assert_equal([2, 3, nil], @row.fields(1, 2, 10))
|
177
|
+
|
178
|
+
# by both
|
179
|
+
assert_equal([2, 3, 4], @row.fields("B", "C", 3))
|
180
|
+
|
181
|
+
# with minimum indices
|
182
|
+
assert_equal([2, 3, 4], @row.fields("B", "C", ["A", 3]))
|
183
|
+
end
|
184
|
+
|
185
|
+
def test_index
|
186
|
+
# basic usage
|
187
|
+
assert_equal(0, @row.index("A"))
|
188
|
+
assert_equal(1, @row.index("B"))
|
189
|
+
assert_equal(2, @row.index("C"))
|
190
|
+
assert_equal(nil, @row.index("Z"))
|
191
|
+
|
192
|
+
# with minimum index
|
193
|
+
assert_equal(0, @row.index("A"))
|
194
|
+
assert_equal(0, @row.index("A", 0))
|
195
|
+
assert_equal(3, @row.index("A", 1))
|
196
|
+
assert_equal(3, @row.index("A", 2))
|
197
|
+
assert_equal(3, @row.index("A", 3))
|
198
|
+
assert_equal(4, @row.index("A", 4))
|
199
|
+
assert_equal(nil, @row.index("A", 5))
|
200
|
+
end
|
201
|
+
|
202
|
+
def test_queries
|
203
|
+
# headers
|
204
|
+
assert(@row.header?("A"))
|
205
|
+
assert(@row.header?("C"))
|
206
|
+
assert(!@row.header?("Z"))
|
207
|
+
assert(@row.include?("A")) # alias
|
208
|
+
|
209
|
+
# fields
|
210
|
+
assert(@row.field?(4))
|
211
|
+
assert(@row.field?(nil))
|
212
|
+
assert(!@row.field?(10))
|
213
|
+
end
|
214
|
+
|
215
|
+
def test_each
|
216
|
+
# array style
|
217
|
+
ary = @row.to_a
|
218
|
+
@row.each do |pair|
|
219
|
+
assert_equal(ary.first.first, pair.first)
|
220
|
+
assert_equal(ary.shift.last, pair.last)
|
221
|
+
end
|
222
|
+
|
223
|
+
# hash style
|
224
|
+
ary = @row.to_a
|
225
|
+
@row.each do |header, field|
|
226
|
+
assert_equal(ary.first.first, header)
|
227
|
+
assert_equal(ary.shift.last, field)
|
228
|
+
end
|
229
|
+
|
230
|
+
# verify that we can chain the call
|
231
|
+
assert_equal(@row, @row.each { })
|
232
|
+
end
|
233
|
+
|
234
|
+
def test_enumerable
|
235
|
+
assert_equal( [["A", 1], ["A", 4], ["A", nil]],
|
236
|
+
@row.select { |pair| pair.first == "A" } )
|
237
|
+
|
238
|
+
assert_equal(10, @row.inject(0) { |sum, (header, n)| sum + (n || 0) })
|
239
|
+
end
|
240
|
+
|
241
|
+
def test_to_a
|
242
|
+
row = FasterCSV::Row.new(%w{A B C}, [1, 2, 3]).to_a
|
243
|
+
assert_instance_of(Array, row)
|
244
|
+
row.each do |pair|
|
245
|
+
assert_instance_of(Array, pair)
|
246
|
+
assert_equal(2, pair.size)
|
247
|
+
end
|
248
|
+
assert_equal([["A", 1], ["B", 2], ["C", 3]], row)
|
249
|
+
end
|
250
|
+
|
251
|
+
def test_to_hash
|
252
|
+
assert_equal({"A" => nil, "B" => 2, "C" => 3}, @row.to_hash)
|
253
|
+
end
|
254
|
+
|
255
|
+
def test_to_csv
|
256
|
+
# normal conversion
|
257
|
+
assert_equal("1,2,3,4,\n", @row.to_csv)
|
258
|
+
assert_equal("1,2,3,4,\n", @row.to_s) # alias
|
259
|
+
|
260
|
+
# with options
|
261
|
+
assert_equal( "1|2|3|4|\r\n",
|
262
|
+
@row.to_csv(:col_sep => "|", :row_sep => "\r\n") )
|
263
|
+
end
|
264
|
+
end
|