rcsv 0.0.8 → 0.0.9
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/Gemfile.lock +1 -1
- data/RELNOTES +3 -0
- data/lib/rcsv.rb +57 -0
- data/lib/rcsv/version.rb +1 -1
- data/test/test_rcsv_raw_parse.rb +1 -1
- data/test/test_rcsv_write.rb +79 -0
- metadata +4 -2
data/Gemfile.lock
CHANGED
data/RELNOTES
CHANGED
data/lib/rcsv.rb
CHANGED
@@ -4,6 +4,11 @@ require "rcsv/version"
|
|
4
4
|
require "stringio"
|
5
5
|
|
6
6
|
class Rcsv
|
7
|
+
|
8
|
+
attr_reader :write_options
|
9
|
+
|
10
|
+
BOOLEAN_FALSE = [nil, false, 0, 'f', 'false']
|
11
|
+
|
7
12
|
def self.parse(csv_data, options = {}, &block)
|
8
13
|
#options = {
|
9
14
|
#:column_separator => "\t",
|
@@ -102,4 +107,56 @@ class Rcsv
|
|
102
107
|
csv_data.pos = initial_position
|
103
108
|
return self.raw_parse(csv_data, raw_options, &block)
|
104
109
|
end
|
110
|
+
|
111
|
+
def initialize(write_options = {})
|
112
|
+
@write_options = write_options
|
113
|
+
@write_options[:column_separator] ||= ','
|
114
|
+
@write_options[:newline_delimiter] ||= "\r\n" # Making Excel happy...
|
115
|
+
@write_options[:header] ||= false
|
116
|
+
end
|
117
|
+
|
118
|
+
def write(io, &block)
|
119
|
+
io.write generate_header if @write_options[:header]
|
120
|
+
while row = yield
|
121
|
+
io.write generate_row(row)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def generate_header
|
126
|
+
return @write_options[:columns].map { |c|
|
127
|
+
c[:name].to_s
|
128
|
+
}.join(@write_options[:column_separator]) << @write_options[:newline_delimiter]
|
129
|
+
end
|
130
|
+
|
131
|
+
def generate_row(row)
|
132
|
+
column_separator = @write_options[:column_separator]
|
133
|
+
csv_row = ''
|
134
|
+
max_index = row.size - 1
|
135
|
+
|
136
|
+
row.each_with_index do |field, index|
|
137
|
+
unquoted_field = process(field, @write_options[:columns][index])
|
138
|
+
# TODO: a better quoting
|
139
|
+
csv_row << (unquoted_field.match(/,/) ? "\"#{unquoted_field}\"" : unquoted_field)
|
140
|
+
csv_row << column_separator unless index == max_index
|
141
|
+
end
|
142
|
+
|
143
|
+
return csv_row << @write_options[:newline_delimiter]
|
144
|
+
end
|
145
|
+
|
146
|
+
protected
|
147
|
+
|
148
|
+
def process(field, column_options)
|
149
|
+
return case column_options[:formatter]
|
150
|
+
when :strftime
|
151
|
+
format = column_options[:format] || "%Y-%m-%d %H:%M:%S %z"
|
152
|
+
field.strftime(format)
|
153
|
+
when :printf
|
154
|
+
format = column_options[:format] || "%s"
|
155
|
+
sprintf(format, field)
|
156
|
+
when :boolean
|
157
|
+
BOOLEAN_FALSE.include?(field.respond_to?(:downcase) ? field.downcase : field) ? 'false' : 'true'
|
158
|
+
else
|
159
|
+
field.to_s
|
160
|
+
end
|
161
|
+
end
|
105
162
|
end
|
data/lib/rcsv/version.rb
CHANGED
data/test/test_rcsv_raw_parse.rb
CHANGED
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'rcsv'
|
3
|
+
|
4
|
+
class RcsvWriteTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@options = {
|
7
|
+
:header => true,
|
8
|
+
:columns => [
|
9
|
+
{
|
10
|
+
:name => 'ID'
|
11
|
+
},
|
12
|
+
{
|
13
|
+
:name => 'Date',
|
14
|
+
:formatter => :strftime,
|
15
|
+
:format => '%Y-%m-%d'
|
16
|
+
},
|
17
|
+
{
|
18
|
+
:name => 'Money',
|
19
|
+
:formatter => :printf,
|
20
|
+
:format => '$%2.2f'
|
21
|
+
},
|
22
|
+
{
|
23
|
+
:name => 'Banana IDDQD'
|
24
|
+
},
|
25
|
+
{
|
26
|
+
:name => nil,
|
27
|
+
:formatter => :boolean
|
28
|
+
}
|
29
|
+
]
|
30
|
+
}
|
31
|
+
|
32
|
+
@data = [
|
33
|
+
[1, Date.parse('2012-11-11'), 100.234, true, nil],
|
34
|
+
[nil, Date.parse('1970-01-02'), -0.1, :nyancat, 0],
|
35
|
+
[3, Date.parse('2012-12-12'), 0, 'sepulka', 'zoop']
|
36
|
+
]
|
37
|
+
|
38
|
+
@writer = Rcsv.new(@options)
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_rcsv_generate_header
|
42
|
+
assert_equal(
|
43
|
+
"ID,Date,Money,Banana IDDQD,\r\n", @writer.generate_header
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_rscv_generate_row
|
48
|
+
assert_equal("1,2012-11-11,$100.23,true,false\r\n", @writer.generate_row(@data.first))
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_rcsv_write
|
52
|
+
io = StringIO.new
|
53
|
+
|
54
|
+
@writer.write(io) do
|
55
|
+
@data.shift
|
56
|
+
end
|
57
|
+
|
58
|
+
io.rewind
|
59
|
+
|
60
|
+
assert_equal(
|
61
|
+
"ID,Date,Money,Banana IDDQD,\r\n1,2012-11-11,$100.23,true,false\r\n,1970-01-02,$-0.10,nyancat,false\r\n3,2012-12-12,$0.00,sepulka,true\r\n", io.read
|
62
|
+
)
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_rcsv_write_no_headers
|
66
|
+
io = StringIO.new
|
67
|
+
@writer.write_options[:header] = false
|
68
|
+
|
69
|
+
@writer.write(io) do
|
70
|
+
@data.shift
|
71
|
+
end
|
72
|
+
|
73
|
+
io.rewind
|
74
|
+
|
75
|
+
assert_equal(
|
76
|
+
"1,2012-11-11,$100.23,true,false\r\n,1970-01-02,$-0.10,nyancat,false\r\n3,2012-12-12,$0.00,sepulka,true\r\n", io.read
|
77
|
+
)
|
78
|
+
end
|
79
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rcsv
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.9
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-01-
|
12
|
+
date: 2013-01-22 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: A libcsv-based CSV parser for Ruby
|
15
15
|
email:
|
@@ -40,6 +40,7 @@ files:
|
|
40
40
|
- rcsv.gemspec
|
41
41
|
- test/test_rcsv.csv
|
42
42
|
- test/test_rcsv_raw_parse.rb
|
43
|
+
- test/test_rcsv_write.rb
|
43
44
|
homepage: http://github.com/fiksu/rcsv
|
44
45
|
licenses: []
|
45
46
|
post_install_message:
|
@@ -69,4 +70,5 @@ summary: Fast CSV parsing library for MRI based on libcsv. Supports type convers
|
|
69
70
|
test_files:
|
70
71
|
- test/test_rcsv.csv
|
71
72
|
- test/test_rcsv_raw_parse.rb
|
73
|
+
- test/test_rcsv_write.rb
|
72
74
|
has_rdoc:
|