array_to_csv 0.0.1 → 0.1.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c1a14acec1c38d14bc166fcc2e3c885a00664747
4
- data.tar.gz: fb3982fb10d8bec759d05fa61de02ed2a9bad320
3
+ metadata.gz: 6a35e265bf29320eaad3cc7455ba66882a062347
4
+ data.tar.gz: 07ccceb8f2ee1868f1de8c812a98b0b5d126799a
5
5
  SHA512:
6
- metadata.gz: 54da663d1c117d226a8f616ef198a6e899f2bad3fa9e2f039482966f189286e90df7869077961db12e00f6b39f448e152cfeefda82c2709c618238d188163dbd
7
- data.tar.gz: f781a7c56fc1bb835649113d704c1efe71e47c361bd692d0efb383047d94b94f0bc368df5af9092b5b04e2fac103879e7e4c16671ad2031e8cb4d56e018a5c27
6
+ metadata.gz: 10d9744daa78f20ab1c7c42a1777f69866339c773f4e7d08b73b361a69a97ae452f5533446c68c66cd4d839adfdd9774859a2ef889808d51a5f836ea2ad31f4e
7
+ data.tar.gz: 68bbacbd8721eb81b4b04c19867a682aa782c4cbf35e10da6fc3d018ceb3e69ac2f1a8b9d7615001381c9f387cbd91ce3ce78d962b53dde372f5e328cae716a2
@@ -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.
@@ -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.1"
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.}
@@ -1,52 +1,41 @@
1
1
  class ArrayToCsv
2
2
 
3
- def initialize array, csv_lib=choose_csv_lib
3
+ require 'array_to_csv/csv_writer'
4
+
5
+ def initialize array, csv_lib=nil
4
6
  @array = array
5
- @csv = csv_lib
7
+ @csv_lib = csv_lib
6
8
  end
7
9
 
8
- def to_csv
9
- @csv.generate do |csv|
10
- each_row do |row|
11
- csv << row
12
- end
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
- def each_row
19
- yield head
20
- @array.each do |hash|
21
- yield row_from_hash hash
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 row_from_hash hash
40
- hash.values_at(*head)
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
- # TODO: return FasterCSV in old ruby
44
- def choose_csv_lib
45
- if RUBY_VERSION =~ /^1\.8/
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
@@ -1,9 +1,14 @@
1
1
  require 'array_to_csv'
2
+ if RUBY_VERSION =~ /^1\.8/
3
+ require 'fastercsv'
4
+ else
5
+ require 'csv'
6
+ end
2
7
 
3
8
  class Array
4
9
 
5
- def to_csv
6
- ArrayToCsv.new(self).to_csv
10
+ def to_csv *args
11
+ ArrayToCsv.new(self).to_csv *args
7
12
  end
8
13
 
9
14
  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
@@ -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
@@ -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.1
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-08 00:00:00.000000000 Z
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