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 ADDED
@@ -0,0 +1,2 @@
1
+ Gemfile.lock
2
+ *.gem
data/cloudxls.gemspec CHANGED
@@ -20,5 +20,5 @@ Gem::Specification.new do |gem|
20
20
 
21
21
  gem.add_development_dependency "minitest"
22
22
  gem.add_development_dependency "rake"
23
- gem.add_development_dependency "webmock"
23
+ gem.add_development_dependency "rspec"
24
24
  end
@@ -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
@@ -1,3 +1,3 @@
1
1
  module CloudXLS
2
- VERSION = '0.3.0'
2
+ VERSION = '0.4.0'
3
3
  end
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
@@ -0,0 +1,10 @@
1
+ ENV["RAILS_ENV"] = 'test'
2
+ require 'bundler'
3
+ require 'bundler/setup'
4
+ require 'cloudxls'
5
+
6
+
7
+ RSpec.configure do |config|
8
+ config.color_enabled = true
9
+ config.order = "random"
10
+ end
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.3.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-19 00:00:00.000000000 Z
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: webmock
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