better_csv 0.0.5 → 0.0.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.
- checksums.yaml +4 -4
- data/lib/better_csv.rb +42 -6
- data/lib/better_csv/version.rb +1 -1
- data/spec/better_csv_spec.rb +151 -108
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 78ea9ac04ffb87e0c08555153c9c07e33395474e
|
4
|
+
data.tar.gz: aa956345ae39f51deecd33da3b60a5e24832434a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6e7ac40b1d13fd3ce9dc45fa08d6be7014e631e60f36202d3f5ab709ba532508f8ed0ec38b99b4bdf3f2afedede4281d6dfd91ed8231d4b557dc173d65da08ec
|
7
|
+
data.tar.gz: eca4e231629e3c8682f00361621a64b9b02e43f9486e669599e05c0c657716d700bfdca75312338c0450bbec9980ec12d6306175cbe4ce3c532b424a90970417
|
data/lib/better_csv.rb
CHANGED
@@ -1,15 +1,51 @@
|
|
1
1
|
require "better_csv/version"
|
2
2
|
|
3
3
|
module BetterCsv
|
4
|
-
|
4
|
+
OPTIONS = [:split_by_comma]
|
5
|
+
|
6
|
+
def self.escape_row value, options: []
|
7
|
+
case value
|
8
|
+
when Array
|
9
|
+
value.collect{|v| "\"#{v.to_s.gsub(/"/,'\"')}\""}
|
10
|
+
when Hash
|
11
|
+
value.values.collect{|v| "\"#{v.to_s.gsub(/"/,'\"')}\""}
|
12
|
+
else
|
13
|
+
if options.include?(:split_by_comma) and value.to_s.include?(',')
|
14
|
+
escape_row(value.to_s.split(',')) #TODO: split by only non escaped comma.
|
15
|
+
else
|
16
|
+
["\"#{value.to_s.gsub(/"/,'\"')}\""]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.escape array, options: []
|
22
|
+
case array
|
23
|
+
when Array
|
24
|
+
array.collect{|v| escape_row(v, options: options)}
|
25
|
+
when Hash
|
26
|
+
array.values.collect{|v| escape_row(v, options: options)}
|
27
|
+
else
|
28
|
+
[escape_row(array.to_s, options: options)]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.build array, options: []
|
33
|
+
escape(array, options: options).collect{|a| a.join(',')}.join("\n")
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.[] array
|
37
|
+
escape(array).collect{|a| a.join(',')}.join("\n")
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.parse str
|
5
41
|
in_literal = false
|
6
42
|
csv = Array.new
|
7
43
|
|
8
|
-
line
|
9
|
-
token
|
10
|
-
back
|
44
|
+
line = []
|
45
|
+
token = ""
|
46
|
+
back = ""
|
11
47
|
current = ""
|
12
|
-
first
|
48
|
+
first = true
|
13
49
|
str.each_char do |c|
|
14
50
|
current = c
|
15
51
|
if first
|
@@ -35,7 +71,7 @@ module BetterCsv
|
|
35
71
|
|
36
72
|
if current == "\n" and not in_literal
|
37
73
|
line << token
|
38
|
-
csv
|
74
|
+
csv << line
|
39
75
|
token = ""
|
40
76
|
yield(line) if block_given?
|
41
77
|
line = Array.new
|
data/lib/better_csv/version.rb
CHANGED
data/spec/better_csv_spec.rb
CHANGED
@@ -5,171 +5,214 @@ describe BetterCsv do
|
|
5
5
|
expect(BetterCsv::VERSION).not_to be nil
|
6
6
|
end
|
7
7
|
|
8
|
-
context '
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
8
|
+
context 'parse' do
|
9
|
+
context 'on basic csv test' do
|
10
|
+
str = 'a,b,c,d,e,f,g'
|
11
|
+
equal = [['a','b','c','d','e','f','g']]
|
12
|
+
|
13
|
+
describe "sepalated with simply ',' == #{str} " do
|
14
|
+
it "shuld be #{equal.to_s}" do
|
15
|
+
expect(BetterCsv.parse(str)).to eq(equal)
|
16
|
+
end
|
15
17
|
end
|
16
18
|
end
|
17
|
-
end
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
context 'on missing first value csv test' do
|
21
|
+
str = ',b,c,d,e,f,g'
|
22
|
+
equal = [['','b','c','d','e','f','g']]
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
describe "sepalated with simply ',' == #{str} " do
|
25
|
+
it "shuld be #{equal.to_s}" do
|
26
|
+
expect(BetterCsv.parse(str)).to eq(equal)
|
27
|
+
end
|
26
28
|
end
|
27
29
|
end
|
28
|
-
end
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
31
|
+
context 'on missing last value csv test' do
|
32
|
+
str = 'b,c,d,e,f,g,'
|
33
|
+
equal = [['b','c','d','e','f','g','']]
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
|
35
|
+
describe "sepalated with simply ',' == #{str} " do
|
36
|
+
it "shuld be #{equal.to_s}" do
|
37
|
+
expect(BetterCsv.parse(str)).to eq(equal)
|
38
|
+
end
|
37
39
|
end
|
38
40
|
end
|
39
|
-
end
|
40
41
|
|
41
|
-
|
42
|
-
|
43
|
-
|
42
|
+
context 'on missing last value csv in more than 1 line csv test' do
|
43
|
+
str = "b,c,d,e,f,g,\nh,i,j,k,l,m,"
|
44
|
+
equal = [['b','c','d','e','f','g',''],['h','i','j','k','l','m','']]
|
44
45
|
|
45
|
-
|
46
|
-
|
47
|
-
|
46
|
+
describe "sepalated with simply ',' == #{str} " do
|
47
|
+
it "shuld be #{equal.to_s}" do
|
48
|
+
expect(BetterCsv.parse(str)).to eq(equal)
|
49
|
+
end
|
48
50
|
end
|
49
51
|
end
|
50
|
-
end
|
51
52
|
|
52
|
-
|
53
|
-
|
54
|
-
|
53
|
+
context 'on missing first value in more than 1 line csv test' do
|
54
|
+
str = ",b,c,d,e,f,g\n,h,i,j,k,l,m"
|
55
|
+
equal = [['','b','c','d','e','f','g'],['','h','i','j','k','l','m']]
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
|
57
|
+
describe "sepalated with simply ',' == #{str} " do
|
58
|
+
it "shuld be #{equal.to_s}" do
|
59
|
+
expect(BetterCsv.parse(str)).to eq(equal)
|
60
|
+
end
|
59
61
|
end
|
60
62
|
end
|
61
|
-
end
|
62
63
|
|
63
|
-
|
64
|
-
|
65
|
-
|
64
|
+
context 'on including nil csv test' do
|
65
|
+
str = 'a,b,,,,f,g'
|
66
|
+
equal = [['a','b',"","","",'f','g']]
|
66
67
|
|
67
|
-
|
68
|
-
|
69
|
-
|
68
|
+
describe "sepalated with simply ',' == #{str} " do
|
69
|
+
it "shuld be #{equal.to_s}" do
|
70
|
+
expect(BetterCsv.parse(str)).to eq(equal)
|
71
|
+
end
|
70
72
|
end
|
71
73
|
end
|
72
|
-
end
|
73
74
|
|
74
|
-
|
75
|
-
|
76
|
-
|
75
|
+
context 'on including "" csv test' do
|
76
|
+
str = 'a,b,,"d",,f,g'
|
77
|
+
equal = [['a','b',"",'d',"",'f','g']]
|
77
78
|
|
78
|
-
|
79
|
-
|
80
|
-
|
79
|
+
describe "sepalated with simply ',' == #{str} " do
|
80
|
+
it "shuld be #{equal.to_s}" do
|
81
|
+
expect(BetterCsv.parse(str)).to eq(equal)
|
82
|
+
end
|
81
83
|
end
|
82
84
|
end
|
83
|
-
end
|
84
85
|
|
85
|
-
|
86
|
-
|
87
|
-
|
86
|
+
context 'on including "" in first csv test' do
|
87
|
+
str = '"a",b,,d,,f,g'
|
88
|
+
equal = [['a','b',"",'d',"",'f','g']]
|
88
89
|
|
89
|
-
|
90
|
-
|
91
|
-
|
90
|
+
describe "sepalated with simply ',' == #{str} " do
|
91
|
+
it "shuld be #{equal.to_s}" do
|
92
|
+
expect(BetterCsv.parse(str)).to eq(equal)
|
93
|
+
end
|
92
94
|
end
|
93
95
|
end
|
94
|
-
end
|
95
96
|
|
96
|
-
|
97
|
-
|
98
|
-
|
97
|
+
context 'on including "" in last csv test' do
|
98
|
+
str = 'a,b,,d,,f,"g"'
|
99
|
+
equal = [['a','b',"",'d',"",'f','g']]
|
99
100
|
|
100
|
-
|
101
|
-
|
102
|
-
|
101
|
+
describe "sepalated with simply ',' == #{str} " do
|
102
|
+
it "shuld be #{equal.to_s}" do
|
103
|
+
expect(BetterCsv.parse(str)).to eq(equal)
|
104
|
+
end
|
103
105
|
end
|
104
106
|
end
|
105
|
-
end
|
106
107
|
|
107
|
-
|
108
|
-
|
109
|
-
|
108
|
+
context 'on including return in "" csv test' do
|
109
|
+
str = %Q(a,b,,"d1\nd2",,f,g)
|
110
|
+
equal = [['a','b',"","d1\nd2","",'f','g']]
|
110
111
|
|
111
|
-
|
112
|
-
|
113
|
-
|
112
|
+
describe "sepalated with simply ',' == #{str} " do
|
113
|
+
it "shuld be #{equal.to_s}" do
|
114
|
+
expect(BetterCsv.parse(str)).to eq(equal)
|
115
|
+
end
|
114
116
|
end
|
115
|
-
end
|
116
117
|
|
117
|
-
|
118
|
-
|
119
|
-
|
118
|
+
describe "each value has native return." do
|
119
|
+
it 'shuld be "d1\nd2"' do
|
120
|
+
expect(BetterCsv.parse(str)[0][3]).to eq("d1\nd2")
|
121
|
+
end
|
120
122
|
end
|
121
123
|
end
|
122
|
-
end
|
123
124
|
|
124
125
|
|
125
|
-
|
126
|
-
|
127
|
-
|
126
|
+
context 'on including comma, in "" csv test' do
|
127
|
+
str = %Q(a,b,,"d1,d2",,f,g)
|
128
|
+
equal = [['a','b',"","d1,d2","",'f','g']]
|
128
129
|
|
129
|
-
|
130
|
-
|
131
|
-
|
130
|
+
describe "sepalated with simply ',' == #{str} " do
|
131
|
+
it "shuld be #{equal.to_s}" do
|
132
|
+
expect(BetterCsv.parse(str)).to eq(equal)
|
133
|
+
end
|
132
134
|
end
|
133
135
|
end
|
134
|
-
end
|
135
136
|
|
136
|
-
|
137
|
-
|
137
|
+
context 'on including comma, in "" csv on multiple lines' do
|
138
|
+
str = <<-EOS
|
138
139
|
a,b,,"d1,d2",,f,g
|
139
140
|
a,b,,"d1,d2",,f,g
|
140
|
-
EOS
|
141
|
-
|
141
|
+
EOS
|
142
|
+
equal = [['a','b',"","d1,d2","",'f','g'],['a','b',"","d1,d2","",'f','g']]
|
142
143
|
|
143
|
-
|
144
|
-
|
145
|
-
|
144
|
+
describe "sepalated with simply ',' == #{str} " do
|
145
|
+
it "shuld be #{equal.to_s}" do
|
146
|
+
expect(BetterCsv.parse(str)).to eq(equal)
|
147
|
+
end
|
146
148
|
end
|
147
149
|
end
|
148
|
-
end
|
149
150
|
|
150
|
-
|
151
|
-
|
151
|
+
context 'on including comma, in "" csv on multiple lines with yield block' do
|
152
|
+
str = <<-EOS
|
152
153
|
a,b,,"d1,d2",,f,g
|
153
154
|
a,b,,"d1,d2",,f,g
|
154
|
-
EOS
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
155
|
+
EOS
|
156
|
+
equal = [['a','b',"","d1,d2","",'f','g'],['a','b',"","d1,d2","",'f','g']]
|
157
|
+
describe "sepalated with simply ',' == #{str} " do
|
158
|
+
it "shuld be raise no error" do
|
159
|
+
expect{
|
160
|
+
BetterCsv.parse(str) do |line|
|
161
|
+
p line
|
162
|
+
end
|
163
|
+
}.to_not raise_error
|
164
|
+
end
|
165
|
+
|
166
|
+
it "shuld be #{equal.to_s}" do
|
167
|
+
expect{
|
168
|
+
BetterCsv.parse(str) do |line|
|
169
|
+
p line
|
170
|
+
end
|
171
|
+
}.to_not raise_error
|
172
|
+
end
|
163
173
|
end
|
174
|
+
end
|
175
|
+
end
|
164
176
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
177
|
+
context 'build' do
|
178
|
+
context 'on array' do
|
179
|
+
it 'should be 2 rows, and 3 values' do
|
180
|
+
eq_str = '"a","b","c"
|
181
|
+
"d","e","f"'
|
182
|
+
expect(BetterCsv[[["a","b","c"],['d','e','f']]]).to eq(eq_str)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
context 'on string without any comma' do
|
187
|
+
it 'should be 1 rows, and 1 values' do
|
188
|
+
eq_str = '"abc"'
|
189
|
+
expect(BetterCsv["abc"]).to eq(eq_str)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
context 'on string with 2 commas.' do
|
194
|
+
it 'should be 1 rows, and 3 values' do
|
195
|
+
eq_str = '"a","b","c"'
|
196
|
+
expect(BetterCsv.build("a,b,c", options:[:split_by_comma])).to eq(eq_str)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
context 'on hash with integer' do
|
201
|
+
it 'should be 3 rows, and 1 each values' do
|
202
|
+
eq_str = '"10"
|
203
|
+
"20"
|
204
|
+
"30"'
|
205
|
+
expect(BetterCsv[{a: 10, b: 20, c: 30}]).to eq(eq_str)
|
171
206
|
end
|
172
207
|
end
|
173
|
-
end
|
174
208
|
|
209
|
+
context 'on hash that parcialy including string with comma' do
|
210
|
+
it 'should be 3 rows, and 3,1,1 values' do
|
211
|
+
eq_str = '"a","b","c"
|
212
|
+
"20"
|
213
|
+
"30"'
|
214
|
+
expect(BetterCsv.build({a: "a,b,c", b: 20, c: 30}, options: [:split_by_comma])).to eq(eq_str)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
175
218
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: better_csv
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tatumaki
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-07-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|