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.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rcsv (0.0.8)
4
+ rcsv (0.0.9)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/RELNOTES CHANGED
@@ -1,3 +1,6 @@
1
+ Version 0.0.9
2
+ * preliminary write support
3
+
1
4
  Version 0.0.8
2
5
  * libcsv upgraded to 3.0.3
3
6
  * :parse_empty_fields_as option added
@@ -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
@@ -1,3 +1,3 @@
1
1
  class Rcsv
2
- VERSION = "0.0.8"
2
+ VERSION = "0.0.9"
3
3
  end
@@ -1,7 +1,7 @@
1
1
  require 'test/unit'
2
2
  require 'rcsv'
3
3
 
4
- class RcsvTest < Test::Unit::TestCase
4
+ class RcsvRawParseTest < Test::Unit::TestCase
5
5
  def setup
6
6
  @csv_data = File.open('test/test_rcsv.csv')
7
7
  end
@@ -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.8
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-11 00:00:00.000000000 Z
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: