array_to_csv 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +102 -0
- data/array_to_csv.gemspec +1 -1
- data/lib/array_to_csv.rb +24 -35
- data/lib/array_to_csv/core_ext.rb +7 -2
- data/lib/array_to_csv/csv_writer.rb +53 -0
- data/spec/array_to_csv_spec.rb +33 -0
- data/spec/core_ext_spec.rb +8 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6a35e265bf29320eaad3cc7455ba66882a062347
|
4
|
+
data.tar.gz: 07ccceb8f2ee1868f1de8c812a98b0b5d126799a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 10d9744daa78f20ab1c7c42a1777f69866339c773f4e7d08b73b361a69a97ae452f5533446c68c66cd4d839adfdd9774859a2ef889808d51a5f836ea2ad31f4e
|
7
|
+
data.tar.gz: 68bbacbd8721eb81b4b04c19867a682aa782c4cbf35e10da6fc3d018ceb3e69ac2f1a8b9d7615001381c9f387cbd91ce3ce78d962b53dde372f5e328cae716a2
|
data/README.md
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
# array_to_csv
|
2
|
+
|
3
|
+
Simple convenience library for converting an array of hashes to CSV
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'array_to_csv'
|
11
|
+
```
|
12
|
+
|
13
|
+
OR
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
gem 'array_to_csv', :require => 'array_to_csv/core_ext'
|
17
|
+
```
|
18
|
+
|
19
|
+
if you want the to_csv method to be added to the Array class.
|
20
|
+
|
21
|
+
Then execute:
|
22
|
+
|
23
|
+
```sh
|
24
|
+
$ bundle install
|
25
|
+
```
|
26
|
+
|
27
|
+
Or install it yourself as:
|
28
|
+
|
29
|
+
```sh
|
30
|
+
$ gem install array_to_csv
|
31
|
+
```
|
32
|
+
|
33
|
+
## Example Usage
|
34
|
+
|
35
|
+
### Using Array#to_csv (re-opening the Array class)
|
36
|
+
|
37
|
+
If you require array_to_csv/core_ext,
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
require 'array_to_csv/core_ext'
|
41
|
+
```
|
42
|
+
|
43
|
+
(or require it from within your Gemfile)
|
44
|
+
you can call to_csv directly on an array.
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
puts [
|
48
|
+
{:first_name => 'Rob', :last_name => 'Bobber'},
|
49
|
+
{:first_name => 'Bob', :age => 103}
|
50
|
+
].to_csv
|
51
|
+
```
|
52
|
+
|
53
|
+
This outputs:
|
54
|
+
|
55
|
+
first_name,last_name,age
|
56
|
+
Rob,Bobber,
|
57
|
+
Rob,,103
|
58
|
+
|
59
|
+
Which would look something like this in your favourite spreadsheet editor
|
60
|
+
|
61
|
+
| first_name | last_name | age |
|
62
|
+
|------------|-----------|-----|
|
63
|
+
| Rob | Bobber | |
|
64
|
+
| Bob | | 103 |
|
65
|
+
|
66
|
+
When no arguments are given to to_csv, the CSV data is returned as a string.
|
67
|
+
|
68
|
+
You can pass in a file path, and the CSV data will be written directly to file,
|
69
|
+
instead of being returned as a string.
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
[
|
73
|
+
{:first_name => 'Rob', :last_name => 'Bobber'},
|
74
|
+
{:first_name => 'Bob', :age => 103}
|
75
|
+
].to_csv("/tmp/people.csv")
|
76
|
+
```
|
77
|
+
|
78
|
+
You can also pass in a File object as the first argument, or any other
|
79
|
+
IO/IO-like object (anything that implements #write(string) and #close).
|
80
|
+
|
81
|
+
### Without reopening Array class
|
82
|
+
|
83
|
+
If you don't want to being reopening core classes, you can convert an array to CSV
|
84
|
+
like this:
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
data = [
|
88
|
+
{:first_name => 'Rob', :last_name => 'Bobber'},
|
89
|
+
{:first_name => 'Bob', :age => 103}
|
90
|
+
]
|
91
|
+
puts ArrayToCsv.new(data).to_csv
|
92
|
+
```
|
93
|
+
|
94
|
+
Which produces the same output as above
|
95
|
+
|
96
|
+
first_name,last_name,age
|
97
|
+
Rob,Bobber,
|
98
|
+
Rob,,103
|
99
|
+
|
100
|
+
The interface for ArrayToCsv#to_csv is the same as that for Array#to_csv.
|
101
|
+
|
102
|
+
You can pass in a file path, File, or IO/IO-like object.
|
data/array_to_csv.gemspec
CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "array_to_csv"
|
7
|
-
spec.version = "0.0
|
7
|
+
spec.version = "0.1.0"
|
8
8
|
spec.authors = ["Joel Plane"]
|
9
9
|
spec.email = ["joel.plane@gmail.com"]
|
10
10
|
spec.description = %q{Adds convenience method Array#to_csv for converting an array of hashes to CSV.}
|
data/lib/array_to_csv.rb
CHANGED
@@ -1,52 +1,41 @@
|
|
1
1
|
class ArrayToCsv
|
2
2
|
|
3
|
-
|
3
|
+
require 'array_to_csv/csv_writer'
|
4
|
+
|
5
|
+
def initialize array, csv_lib=nil
|
4
6
|
@array = array
|
5
|
-
@
|
7
|
+
@csv_lib = csv_lib
|
6
8
|
end
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
# @return [String, nil]
|
11
|
+
def to_csv io_or_file_path=nil
|
12
|
+
case io_or_file_path
|
13
|
+
when nil
|
14
|
+
to_csv_string
|
15
|
+
when String
|
16
|
+
to_csv_file io_or_file_path
|
17
|
+
else
|
18
|
+
to_csv_io io_or_file_path
|
13
19
|
end
|
14
20
|
end
|
15
21
|
|
16
22
|
private
|
17
23
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def head
|
26
|
-
@head_from_array ||= [].tap do |keys|
|
27
|
-
seen_keys = {}
|
28
|
-
@array.each do |hash|
|
29
|
-
hash.keys.each do |key|
|
30
|
-
unless seen_keys[key]
|
31
|
-
seen_keys[key] = true
|
32
|
-
keys << key
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
24
|
+
# @return [String]
|
25
|
+
def to_csv_string
|
26
|
+
StringIO.new.tap do |string_io|
|
27
|
+
self.to_csv string_io
|
28
|
+
end.string
|
37
29
|
end
|
38
30
|
|
39
|
-
def
|
40
|
-
|
31
|
+
def to_csv_file file_path
|
32
|
+
file_io = File.open(file_path, 'w')
|
33
|
+
self.to_csv file_io
|
41
34
|
end
|
42
35
|
|
43
|
-
#
|
44
|
-
def
|
45
|
-
|
46
|
-
FasterCSV
|
47
|
-
else
|
48
|
-
CSV
|
49
|
-
end
|
36
|
+
# @return [nil]
|
37
|
+
def to_csv_io io
|
38
|
+
CsvWriter.new(@array, io, @csv_lib).write
|
50
39
|
end
|
51
40
|
|
52
41
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
class ArrayToCsv::CsvWriter
|
2
|
+
|
3
|
+
def initialize array, io, csv_lib
|
4
|
+
@array, @io = array, io
|
5
|
+
@csv = csv_lib || choose_csv_lib
|
6
|
+
end
|
7
|
+
|
8
|
+
def write
|
9
|
+
each_row do |row|
|
10
|
+
write_line row
|
11
|
+
end
|
12
|
+
@io.close
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def write_line row
|
17
|
+
@io.write @csv.generate_line row
|
18
|
+
end
|
19
|
+
|
20
|
+
def each_row
|
21
|
+
yield head
|
22
|
+
@array.each do |hash|
|
23
|
+
yield row_from_hash hash
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def head
|
28
|
+
@head_from_array ||= [].tap do |keys|
|
29
|
+
seen_keys = {}
|
30
|
+
@array.each do |hash|
|
31
|
+
hash.keys.each do |key|
|
32
|
+
unless seen_keys[key]
|
33
|
+
seen_keys[key] = true
|
34
|
+
keys << key
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def row_from_hash hash
|
42
|
+
hash.values_at(*head)
|
43
|
+
end
|
44
|
+
|
45
|
+
def choose_csv_lib
|
46
|
+
if RUBY_VERSION =~ /^1\.8/
|
47
|
+
FasterCSV
|
48
|
+
else
|
49
|
+
CSV
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
data/spec/array_to_csv_spec.rb
CHANGED
@@ -41,4 +41,37 @@ describe ArrayToCsv do
|
|
41
41
|
|
42
42
|
end
|
43
43
|
|
44
|
+
describe ".to_csv(io)" do
|
45
|
+
|
46
|
+
subject { ArrayToCsv.new([{:key1 => 'value1'}, {:key2 => 'value2'}]) }
|
47
|
+
|
48
|
+
it "should stream output to provided io object" do
|
49
|
+
io = double
|
50
|
+
expect(io).to receive(:write).with("key1,key2\n")
|
51
|
+
expect(io).to receive(:write).with("value1,\n")
|
52
|
+
expect(io).to receive(:write).with(",value2\n")
|
53
|
+
expect(io).to receive(:close)
|
54
|
+
subject.to_csv(io)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should return nil" do
|
58
|
+
io = double :write => nil, :close => nil
|
59
|
+
expect(subject.to_csv(io)).to be_nil
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
describe ".to_csv(file_path)" do
|
65
|
+
|
66
|
+
subject { ArrayToCsv.new([{:key1 => 'value1'}, {:key2 => 'value2'}]) }
|
67
|
+
let(:csv_output) { "key1,key2\nvalue1,\n,value2\n" }
|
68
|
+
let(:test_path) { "/tmp/array_to_csv_test_output.csv" }
|
69
|
+
|
70
|
+
it "should write CSV to file" do
|
71
|
+
subject.to_csv test_path
|
72
|
+
expect(File.read(test_path)).to eq(csv_output)
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
44
77
|
end
|
data/spec/core_ext_spec.rb
CHANGED
@@ -16,4 +16,12 @@ describe "array_to_csv/core_ext" do
|
|
16
16
|
expect(array.to_csv).to eq(ArrayToCsv.new(array).to_csv)
|
17
17
|
end
|
18
18
|
|
19
|
+
it "should delegate with arguments" do
|
20
|
+
array = []
|
21
|
+
fake_io, inst = double, double
|
22
|
+
expect(ArrayToCsv).to receive(:new).and_return(inst)
|
23
|
+
expect(inst).to receive(:to_csv).with(fake_io)
|
24
|
+
array.to_csv fake_io
|
25
|
+
end
|
26
|
+
|
19
27
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: array_to_csv
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joel Plane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-06-
|
11
|
+
date: 2014-06-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -63,10 +63,12 @@ files:
|
|
63
63
|
- .gitignore
|
64
64
|
- Gemfile
|
65
65
|
- LICENSE.txt
|
66
|
+
- README.md
|
66
67
|
- Rakefile
|
67
68
|
- array_to_csv.gemspec
|
68
69
|
- lib/array_to_csv.rb
|
69
70
|
- lib/array_to_csv/core_ext.rb
|
71
|
+
- lib/array_to_csv/csv_writer.rb
|
70
72
|
- spec/array_to_csv_spec.rb
|
71
73
|
- spec/core_ext_spec.rb
|
72
74
|
- test_helper.rb
|