cloudxls 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/cloudxls.gemspec +1 -1
- data/lib/cloudxls/csv_writer.rb +108 -0
- data/lib/cloudxls/version.rb +1 -1
- data/lib/cloudxls.rb +2 -1
- data/spec/csv_writer_spec.rb +86 -0
- data/spec/spec_helper.rb +10 -0
- metadata +10 -5
- data/Gemfile.lock +0 -32
data/.gitignore
ADDED
data/cloudxls.gemspec
CHANGED
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'csv'
|
2
|
+
|
3
|
+
module CloudXLS
|
4
|
+
class CSVWriter
|
5
|
+
DATETIME_FORMAT = "%FT%T.%L%z".freeze
|
6
|
+
DATE_FORMAT = "%F".freeze
|
7
|
+
|
8
|
+
# Generates CSV string.
|
9
|
+
#
|
10
|
+
# @param [Array<String/Symbol>] columns
|
11
|
+
# Method/attribute keys to for the export.
|
12
|
+
#
|
13
|
+
# @return [String]
|
14
|
+
# The full CSV as a string. Titleizes *columns* for the header.
|
15
|
+
#
|
16
|
+
def self.text(scope, options = {})
|
17
|
+
columns = options[:columns]
|
18
|
+
|
19
|
+
str = ::CSV.generate do |csv|
|
20
|
+
|
21
|
+
if options[:skip_headers] != true
|
22
|
+
if scope.respond_to?(:column_names)
|
23
|
+
columns ||= scope.column_names
|
24
|
+
end
|
25
|
+
if columns
|
26
|
+
csv << csv_titles(columns, :titleize)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
enum = scope_enumerator(scope)
|
31
|
+
scope.send(enum) do |record|
|
32
|
+
csv << csv_row(record, columns)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
str.strip!
|
36
|
+
end
|
37
|
+
|
38
|
+
# Example
|
39
|
+
#
|
40
|
+
# Post.csv_enumerator(Post.all, [:title, :author, :published_at])
|
41
|
+
#
|
42
|
+
# @param [ActiveRecord::Scope] scope
|
43
|
+
# An activerecord scope object for the records to be exported.
|
44
|
+
# Example: Post.all.limit(500).where(author: "foo")
|
45
|
+
#
|
46
|
+
# @return [Enumerator] enumerator to use for streaming response.
|
47
|
+
#
|
48
|
+
def self.enumerator(scope, options = {})
|
49
|
+
columns = options[:columns]
|
50
|
+
|
51
|
+
Enumerator.new do |row|
|
52
|
+
if options[:skip_headers] != true
|
53
|
+
if scope.respond_to?(:column_names)
|
54
|
+
columns ||= scope.column_names
|
55
|
+
end
|
56
|
+
if columns
|
57
|
+
row << csv_titles(columns, :titleize).to_csv
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
enum = scope_enumerator(scope)
|
62
|
+
scope.send(enum) do |record|
|
63
|
+
row << csv_row(record, columns).to_csv
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
|
71
|
+
def self.csv_row(obj, columns = [])
|
72
|
+
if obj.is_a?(Array)
|
73
|
+
obj.map{ |el| encode_for_csv(el) }
|
74
|
+
else
|
75
|
+
columns.map do |key|
|
76
|
+
encode_for_csv(obj.send(key))
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
def self.encode_for_csv(val)
|
83
|
+
case val
|
84
|
+
when DateTime,Time then val.strftime(DATETIME_FORMAT)
|
85
|
+
when Date then val.strftime(DATE_FORMAT)
|
86
|
+
else
|
87
|
+
val
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.csv_titles(column_names, strategy = :titleize)
|
92
|
+
column_names.map do |c|
|
93
|
+
title = c.to_s
|
94
|
+
title = title.send(strategy) if title.respond_to?(strategy)
|
95
|
+
title
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
def self.scope_enumerator(scope)
|
101
|
+
if scope.respond_to?(:find_each)
|
102
|
+
:find_each
|
103
|
+
else
|
104
|
+
:each
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
data/lib/cloudxls/version.rb
CHANGED
data/lib/cloudxls.rb
CHANGED
@@ -6,12 +6,13 @@ require 'rest_client'
|
|
6
6
|
require 'multi_json'
|
7
7
|
|
8
8
|
require 'cloudxls/version'
|
9
|
+
require 'cloudxls/csv_writer'
|
9
10
|
|
10
11
|
module CloudXLS
|
11
12
|
@https = true
|
12
13
|
@api_base = 'cloudxls.com'.freeze
|
13
14
|
@api_key = ENV["CLOUDXLS_API_KEY"]
|
14
|
-
@ssl_bundle_path = File.dirname(__FILE__) + '/data/ca-certificates.crt'
|
15
|
+
# @ssl_bundle_path = File.dirname(__FILE__) + '/data/ca-certificates.crt'
|
15
16
|
@verify_ssl_certs = true
|
16
17
|
|
17
18
|
class << self
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "CloudXLS::CSVWriter" do
|
4
|
+
before do
|
5
|
+
@writer = CloudXLS::CSVWriter
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "with array" do
|
9
|
+
it "should not titleize" do
|
10
|
+
expect( @writer.text([['foo','bar'],[1,2]]) ).to eq("foo,bar\n1,2")
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should escape titles" do
|
14
|
+
expect( @writer.text([['bar"baz']]) ).to eq("\"bar\"\"baz\"")
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should escape rows" do
|
18
|
+
expect( @writer.text([['title'],['bar"baz']]) ).to eq("title\n\"bar\"\"baz\"")
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should write YYYY-MM-DD for Date" do
|
22
|
+
expect( @writer.text([[Date.new(2012,12,24)]]) ).to eq("2012-12-24")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should write xmlschema for DateTime" do
|
26
|
+
# TODO: make UTC consistent
|
27
|
+
expect( @writer.text([[DateTime.new(2012,12,24,18,30,5,'+0000')]]) ).to eq("2012-12-24T18:30:05.000+0000")
|
28
|
+
expect( @writer.text([[DateTime.new(2012,12,24,18,30,5,'+0000').to_time.utc]]) ).to eq("2012-12-24T18:30:05.000+0000")
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should write nothing for nil" do
|
32
|
+
expect( @writer.text([[nil,nil]]) ).to eq(",")
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should write \"\" for empty string" do
|
36
|
+
expect( @writer.text([["",""]]) ).to eq('"",""')
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should write integers" do
|
40
|
+
expect( @writer.text([[-1,0,1,1_000_000]]) ).to eq('-1,0,1,1000000')
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should write floats" do
|
44
|
+
expect( @writer.text([[-1.0,0.0,1.0,1_000_000.0,1.234567]]) ).to eq('-1.0,0.0,1.0,1000000.0,1.234567')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# describe "#text with AR" do
|
49
|
+
# before do
|
50
|
+
# Post.delete_all
|
51
|
+
# @post = Post.create(
|
52
|
+
# :title => "hello world",
|
53
|
+
# :visits => 12_032,
|
54
|
+
# :conversion_rate => 0.24,
|
55
|
+
# :published_on => Date.new(2013,12,24),
|
56
|
+
# :expired_at => DateTime.new(2013,12,25,12,30,30),
|
57
|
+
# :unix_timestamp => DateTime.new(2013,12,25,12,30,30),
|
58
|
+
# :published => false)
|
59
|
+
# end
|
60
|
+
|
61
|
+
# it "given no records should just return titles" do
|
62
|
+
# Post.delete_all
|
63
|
+
# expect( @writer.text(Post.all, :columns => [:title, :visits]) ).to eq("Title,Visits")
|
64
|
+
# end
|
65
|
+
|
66
|
+
# it "should work with a Post.all" do
|
67
|
+
# expect( @writer.text(Post.all, :columns => [:title, :visits]) ).to eq("Title,Visits\nhello world,12032")
|
68
|
+
# end
|
69
|
+
|
70
|
+
# it "should work with a Post.limit" do
|
71
|
+
# expect( @writer.text(Post.limit(10), :columns => [:title, :visits]) ).to eq("Title,Visits\nhello world,12032")
|
72
|
+
# end
|
73
|
+
|
74
|
+
# it "should work with a Post.all.to_a" do
|
75
|
+
# expect( @writer.text(Post.all.to_a, :columns => [:title, :visits]) ).to eq("Title,Visits\nhello world,12032")
|
76
|
+
# end
|
77
|
+
|
78
|
+
# it "should write xmlschema for DateTime" do
|
79
|
+
# expect( @writer.text(Post.all, :columns => [:expired_at]) ).to eq("Expired At\n2013-12-25T12:30:30.000+0000")
|
80
|
+
# end
|
81
|
+
|
82
|
+
# it "should write YYYY-MM-DD for Date" do
|
83
|
+
# expect( @writer.text(Post.all, :columns => [:published_on]) ).to eq("Published On\n2013-12-24")
|
84
|
+
# end
|
85
|
+
# end
|
86
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cloudxls
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
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-11-
|
12
|
+
date: 2013-11-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rest-client
|
@@ -82,7 +82,7 @@ dependencies:
|
|
82
82
|
- !ruby/object:Gem::Version
|
83
83
|
version: '0'
|
84
84
|
- !ruby/object:Gem::Dependency
|
85
|
-
name:
|
85
|
+
name: rspec
|
86
86
|
requirement: !ruby/object:Gem::Requirement
|
87
87
|
none: false
|
88
88
|
requirements:
|
@@ -104,14 +104,17 @@ executables: []
|
|
104
104
|
extensions: []
|
105
105
|
extra_rdoc_files: []
|
106
106
|
files:
|
107
|
+
- .gitignore
|
107
108
|
- Gemfile
|
108
|
-
- Gemfile.lock
|
109
109
|
- README.md
|
110
110
|
- Rakefile
|
111
111
|
- cloudxls.gemspec
|
112
112
|
- lib/cloudxls.rb
|
113
|
+
- lib/cloudxls/csv_writer.rb
|
113
114
|
- lib/cloudxls/version.rb
|
114
115
|
- lib/data/ca-certificates.txt
|
116
|
+
- spec/csv_writer_spec.rb
|
117
|
+
- spec/spec_helper.rb
|
115
118
|
homepage: https://cloudxls.com
|
116
119
|
licenses: []
|
117
120
|
post_install_message:
|
@@ -136,4 +139,6 @@ rubygems_version: 1.8.23
|
|
136
139
|
signing_key:
|
137
140
|
specification_version: 3
|
138
141
|
summary: Ruby wrapper for the CloudXLS xpipe API
|
139
|
-
test_files:
|
142
|
+
test_files:
|
143
|
+
- spec/csv_writer_spec.rb
|
144
|
+
- spec/spec_helper.rb
|
data/Gemfile.lock
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
cloudxls (0.1.0)
|
5
|
-
multi_json (>= 1.0.4, < 2)
|
6
|
-
rest-client (~> 1.4)
|
7
|
-
|
8
|
-
GEM
|
9
|
-
remote: https://rubygems.org/
|
10
|
-
specs:
|
11
|
-
addressable (2.3.5)
|
12
|
-
crack (0.4.1)
|
13
|
-
safe_yaml (~> 0.9.0)
|
14
|
-
mime-types (1.25)
|
15
|
-
minitest (5.0.8)
|
16
|
-
multi_json (1.8.0)
|
17
|
-
rake (10.1.0)
|
18
|
-
rest-client (1.6.7)
|
19
|
-
mime-types (>= 1.16)
|
20
|
-
safe_yaml (0.9.7)
|
21
|
-
webmock (1.13.0)
|
22
|
-
addressable (>= 2.2.7)
|
23
|
-
crack (>= 0.3.2)
|
24
|
-
|
25
|
-
PLATFORMS
|
26
|
-
ruby
|
27
|
-
|
28
|
-
DEPENDENCIES
|
29
|
-
cloudxls!
|
30
|
-
minitest
|
31
|
-
rake
|
32
|
-
webmock
|