cloudxls 0.3.0 → 0.4.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.
- 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
|