gibbon 1.1.5 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of gibbon might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -2
- data/Gemfile +4 -0
- data/LICENSE.txt +1 -1
- data/README.markdown +23 -5
- data/gibbon.gemspec +2 -1
- data/lib/gibbon/api_category.rb +19 -21
- data/lib/gibbon/export.rb +42 -19
- data/lib/gibbon/version.rb +3 -0
- data/spec/gibbon/gibbon_spec.rb +40 -10
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3568033ceac76caeac9a0c242498bea98928a54b
|
4
|
+
data.tar.gz: 5eaee69f08c43608056f4407058ae68db18ae062
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6aee46b63e30a3d8b2178864c76f773edc36d4b2f0dbe9c64feecf5b79fba5e008cbb71ce0af31f9deb1c9ab96a0ff85bbe4cfd443187ee7335e90ad10df6c74
|
7
|
+
data.tar.gz: 1054e23dc767ec9d60b507febdaecc2c646cfcac98c149b4a35b35cced3ab2c1d98b1e51c25c8c892f8ca0ddbe019ce21dba6a9bdca46b9c94378785998d8566
|
data/CHANGELOG.md
CHANGED
@@ -1,12 +1,19 @@
|
|
1
1
|
## [Unreleased][unreleased]
|
2
2
|
-
|
3
|
+
|
4
|
+
## [1.2.0] - 2015-07-16
|
5
|
+
- Same as 1.1.6 but rereleased because it's a breaking change
|
6
|
+
- Support for Ruby 2 streaming with Export API. Now returns an Array of Array of Strings instead of an Array of Strings.
|
7
|
+
- Fix a bug that caused calling methods statically on Gibbon::Export to fail
|
8
|
+
|
9
|
+
## [1.1.6] - 2015-06-04 (Yanked)
|
10
|
+
- Support for Ruby 2 streaming with Export API
|
11
|
+
|
3
12
|
## [1.1.5] - 2015-02-19
|
4
|
-
### Fixed
|
5
13
|
- Update MultiJSON dependency to 1.9.0
|
6
14
|
- Handle single empty space in Export API response
|
7
15
|
|
8
16
|
## [1.1.4] - 2012-11-04
|
9
|
-
### Fixed
|
10
17
|
- Fix JSON::ParserError on export calls that return blank results
|
11
18
|
|
12
19
|
[unreleased]: https://github.com/amro/gibbon/compare/v1.1.5...HEAD
|
data/Gemfile
CHANGED
data/LICENSE.txt
CHANGED
data/README.markdown
CHANGED
@@ -9,9 +9,8 @@ Gibbon is an API wrapper for MailChimp's [Primary and Export APIs](http://www.ma
|
|
9
9
|
Gibbon now targets MailChimp API 2.0, which is substantially different from API 1.3. Please use Gibbon 0.4.6 if you need to use API 1.3.
|
10
10
|
|
11
11
|
* Supports MailChimp API 2.0 and Export API 1.0
|
12
|
-
* Errors are raised by default
|
12
|
+
* Errors are raised by default
|
13
13
|
* Timeouts can be specified per request during initialization
|
14
|
-
* Ruby 1.9.3+ for now. A future version may be Ruby 2.0 only to take advantage of lazy iteration when using the Export API.
|
15
14
|
|
16
15
|
##Installation
|
17
16
|
|
@@ -190,7 +189,26 @@ of JSON objects rather than a single JSON array.
|
|
190
189
|
|
191
190
|
For example, dumping list members via the "list" method works like this:
|
192
191
|
|
193
|
-
gibbon_export.list({:id => list_id})
|
192
|
+
gibbon_export.list({:id => *list_id*})
|
193
|
+
|
194
|
+
One can also use this in a streaming fashion, where each row is parsed on it comes in like this:
|
195
|
+
|
196
|
+
gibbon_export.list({:id => *list_id*}) { |row| *do_sth_with* row }
|
197
|
+
|
198
|
+
For the streaming functionality, it is important to supply an explicit block / procedure to the export functions, not an implicit one. So, the preceding and following one will work. Please note this method also includes a counter (*i*, starting at 0) telling which row of data you're receiving:
|
199
|
+
```
|
200
|
+
method = Proc.new do |row, i|
|
201
|
+
*do_sth_with* row
|
202
|
+
end
|
203
|
+
gibbon_export.list(params, &method)
|
204
|
+
```
|
205
|
+
|
206
|
+
Please note, the following example gives a block that is outside of the function and therefore **won't** work:
|
207
|
+
```
|
208
|
+
gibbon_export.list({:id => *list_id*}) do |row|
|
209
|
+
*do_sth_with* row
|
210
|
+
end
|
211
|
+
```
|
194
212
|
|
195
213
|
##Thanks
|
196
214
|
|
@@ -198,5 +216,5 @@ Thanks to everyone who's [contributed](https://github.com/amro/gibbon/contributo
|
|
198
216
|
|
199
217
|
##Copyright
|
200
218
|
|
201
|
-
* Copyright (c) 2010-
|
202
|
-
* MailChimp (c) 2001-
|
219
|
+
* Copyright (c) 2010-2015 Amro Mousa. See LICENSE.txt for details.
|
220
|
+
* MailChimp (c) 2001-2015 The Rocket Science Group.
|
data/gibbon.gemspec
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require 'gibbon/version'
|
3
4
|
|
4
5
|
Gem::Specification.new do |s|
|
5
6
|
s.name = "gibbon"
|
6
|
-
s.version =
|
7
|
+
s.version = Gibbon::VERSION
|
7
8
|
s.authors = ["Amro Mousa"]
|
8
9
|
s.email = ["amromousa@gmail.com"]
|
9
10
|
s.homepage = "http://github.com/amro/gibbon"
|
data/lib/gibbon/api_category.rb
CHANGED
@@ -27,27 +27,26 @@ module Gibbon
|
|
27
27
|
headers = params.delete(:headers) || {}
|
28
28
|
response = self.class.post(api_url, :body => MultiJson.dump(params), :headers => headers, :timeout => @timeout)
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
if should_raise_for_response?(parsed_response)
|
44
|
-
error = MailChimpError.new(parsed_response["error"])
|
45
|
-
error.code = parsed_response["code"]
|
46
|
-
error.name = parsed_response["name"]
|
47
|
-
raise error
|
48
|
-
end
|
30
|
+
parse_response(response.body) if response.body
|
31
|
+
end
|
32
|
+
|
33
|
+
def parse_response(response, check_error = true)
|
34
|
+
begin
|
35
|
+
parsed_response = MultiJson.load(response)
|
36
|
+
rescue MultiJson::ParseError
|
37
|
+
parsed_response = {
|
38
|
+
"error" => "Unparseable response: #{response}",
|
39
|
+
"name" => "UNPARSEABLE_RESPONSE",
|
40
|
+
"code" => 500
|
41
|
+
}
|
49
42
|
end
|
50
43
|
|
44
|
+
if should_raise_for_response?(parsed_response)
|
45
|
+
error = MailChimpError.new(parsed_response["error"])
|
46
|
+
error.code = parsed_response["code"]
|
47
|
+
error.name = parsed_response["name"]
|
48
|
+
raise error
|
49
|
+
end
|
51
50
|
parsed_response
|
52
51
|
end
|
53
52
|
|
@@ -61,7 +60,7 @@ module Gibbon
|
|
61
60
|
if ((args.length > 0) && args[0].is_a?(Hash))
|
62
61
|
method_missing(:send, args[0])
|
63
62
|
else
|
64
|
-
__send__(args)
|
63
|
+
__send__(*args)
|
65
64
|
end
|
66
65
|
end
|
67
66
|
|
@@ -100,7 +99,6 @@ module Gibbon
|
|
100
99
|
data_center
|
101
100
|
end
|
102
101
|
|
103
|
-
|
104
102
|
private
|
105
103
|
|
106
104
|
def ensure_api_key(params)
|
data/lib/gibbon/export.rb
CHANGED
@@ -14,37 +14,51 @@ module Gibbon
|
|
14
14
|
"http://#{get_data_center_from_api_key}api.mailchimp.com/export/1.0/"
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
|
-
|
17
|
+
# fsluis: Alternative, streaming, interface to mailchimp export api
|
18
|
+
# Prevents having to keep lots of data in memory
|
19
|
+
def call(method, params = {}, &block)
|
20
|
+
rows = []
|
19
21
|
|
20
22
|
api_url = export_api_url + method + "/"
|
21
23
|
params = @default_params.merge(params).merge({:apikey => @api_key})
|
22
|
-
|
23
|
-
|
24
|
-
lines = response.body.lines
|
25
|
-
if @throws_exceptions
|
26
|
-
# ignore blank responses
|
27
|
-
return [] if !lines.first || lines.first.strip.empty?
|
28
|
-
|
29
|
-
first_line = MultiJson.load(lines.first) if lines.first
|
24
|
+
block = Proc.new { |row| rows << row } unless block_given?
|
25
|
+
ensure_api_key params
|
30
26
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
27
|
+
url = URI.parse(api_url)
|
28
|
+
req = Net::HTTP::Post.new(url.path, initheader = {'Content-Type' => 'application/json'})
|
29
|
+
req.body = MultiJson.dump(params)
|
30
|
+
Net::HTTP.start(url.host, url.port, :read_timeout => @timeout) do |http|
|
31
|
+
# http://stackoverflow.com/questions/29598196/ruby-net-http-read-body-nethttpokread-body-called-twice-ioerror
|
32
|
+
http.request req do |response|
|
33
|
+
i = -1
|
34
|
+
last = ''
|
35
|
+
response.read_body do |chunk|
|
36
|
+
next if chunk.nil? or chunk.strip.empty?
|
37
|
+
lines = (last+chunk).split("\n")
|
38
|
+
last = lines.pop || ''
|
39
|
+
lines.each do |line|
|
40
|
+
block.call(parse_response(line, i < 0), i += 1) unless line.nil?
|
41
|
+
end
|
42
|
+
end
|
43
|
+
block.call(parse_response(last, i < 0), i += 1) unless last.nil? or last.empty?
|
35
44
|
end
|
36
45
|
end
|
46
|
+
rows unless block_given?
|
47
|
+
end
|
37
48
|
|
38
|
-
|
49
|
+
def parse_response(res, check_error)
|
50
|
+
return [] if res.strip.empty?
|
51
|
+
super(res, check_error)
|
39
52
|
end
|
40
53
|
|
41
54
|
def set_instance_defaults
|
42
|
-
super
|
43
55
|
@api_key = self.class.api_key if @api_key.nil?
|
44
56
|
@timeout = self.class.timeout if @timeout.nil?
|
57
|
+
super
|
45
58
|
end
|
46
59
|
|
47
|
-
|
60
|
+
# fsluis: added a &block to this method and function call
|
61
|
+
def method_missing(method, *args, &block)
|
48
62
|
# To support underscores, we camelize the method name
|
49
63
|
|
50
64
|
# Thanks for the camelize gsub, Rails
|
@@ -55,16 +69,25 @@ module Gibbon
|
|
55
69
|
# must be upcased (See "Campaign Report Data Methods" in their API docs).
|
56
70
|
method = method[0].chr.downcase + method[1..-1].gsub(/aim$/i, 'AIM')
|
57
71
|
|
58
|
-
call(method, *args)
|
72
|
+
call(method, *args, &block)
|
59
73
|
end
|
60
74
|
|
61
75
|
def respond_to_missing?(method, include_private = false)
|
62
76
|
%w{list ecommOrders ecomm_orders campaignSubscriberActivity campaign_subscriber_activity}.include?(method.to_s) || super
|
63
77
|
end
|
64
78
|
|
65
|
-
|
66
79
|
private
|
67
80
|
|
81
|
+
def split_json(lines, delimiter)
|
82
|
+
lines.map do |line|
|
83
|
+
if line.include? delimiter
|
84
|
+
line.split(delimiter).each_with_index.map{ |s, i| i % 2 == 0 ? s + delimiter[0] : delimiter[1] + s }
|
85
|
+
else
|
86
|
+
line
|
87
|
+
end
|
88
|
+
end.flatten
|
89
|
+
end
|
90
|
+
|
68
91
|
def ensure_api_key(params)
|
69
92
|
unless @api_key || @default_params[:apikey] || params[:apikey]
|
70
93
|
raise Gibbon::GibbonError, "You must set an api_key prior to making a call"
|
data/spec/gibbon/gibbon_spec.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'cgi'
|
3
|
+
require 'webmock'
|
4
|
+
require 'webmock/rspec'
|
3
5
|
|
4
6
|
describe Gibbon do
|
5
7
|
|
@@ -229,7 +231,8 @@ describe Gibbon do
|
|
229
231
|
@gibbon = Gibbon::Export.new(@key)
|
230
232
|
@url = "http://us1.api.mailchimp.com/export/1.0/"
|
231
233
|
@body = {:apikey => @key, :id => "listid"}
|
232
|
-
@
|
234
|
+
@return_items = ["array", "entries"]
|
235
|
+
@returns = MultiJson.dump(@return_items)
|
233
236
|
end
|
234
237
|
|
235
238
|
it "handle api key with dc" do
|
@@ -237,43 +240,70 @@ describe Gibbon do
|
|
237
240
|
@gibbon = Gibbon::Export.new(@api_key)
|
238
241
|
|
239
242
|
@body[:apikey] = @api_key
|
240
|
-
params = {:body => MultiJson.dump(@body), :timeout => 30}
|
241
|
-
|
242
243
|
url = @url.gsub('us1', 'us2') + "sayHello/"
|
243
|
-
|
244
|
+
|
245
|
+
# Fake request
|
246
|
+
stub_request(:post, url).
|
247
|
+
to_return(:body => @returns, :status => 200)
|
248
|
+
|
249
|
+
# Check request url
|
244
250
|
@gibbon.say_hello(@body)
|
251
|
+
expect(WebMock).to have_requested(:post, url).with(:body => @body)
|
252
|
+
end
|
253
|
+
|
254
|
+
it "uses timeout if set" do
|
255
|
+
Gibbon::Export.timeout = 45
|
256
|
+
expect(Gibbon::Export.new.timeout).to eql 45
|
245
257
|
end
|
246
258
|
|
247
259
|
it "not throw exception if the Export API replies with a JSON hash containing a key called 'error'" do
|
248
260
|
@gibbon.throws_exceptions = false
|
249
|
-
|
261
|
+
reply = MultiJson.dump({:error => 'bad things'})
|
262
|
+
stub_request(:post, @url + 'sayHello/').
|
263
|
+
to_return(:body => reply, :status => 200)
|
250
264
|
|
251
265
|
@gibbon.say_hello(@body)
|
252
266
|
end
|
253
267
|
|
254
268
|
it "throw exception if configured to and the Export API replies with a JSON hash containing a key called 'error'" do
|
255
269
|
@gibbon.throws_exceptions = true
|
256
|
-
|
257
|
-
|
258
|
-
|
270
|
+
reply = MultiJson.dump({:error => 'bad things', :code => '123'})
|
271
|
+
stub_request(:post, @url + 'sayHello/').
|
272
|
+
to_return(:body => reply, :status => 200)
|
259
273
|
|
260
274
|
expect {@gibbon.say_hello(@body)}.to raise_error(Gibbon::MailChimpError)
|
261
275
|
end
|
262
276
|
|
263
277
|
it "should handle a single empty space response without throwing an exception" do
|
264
278
|
@gibbon.throws_exceptions = true
|
265
|
-
|
279
|
+
stub_request(:post, @url + 'sayHello/').
|
280
|
+
to_return(:body => " ", :status => 200)
|
281
|
+
#allow(Gibbon::Export).to receive(:post).and_return(Struct.new(:body).new(" "))
|
266
282
|
|
267
283
|
expect(@gibbon.say_hello(@body)).to eq([])
|
268
284
|
end
|
269
285
|
|
270
286
|
it "should handle an empty response without throwing an exception" do
|
271
287
|
@gibbon.throws_exceptions = true
|
272
|
-
|
288
|
+
stub_request(:post, @url + 'sayHello/').
|
289
|
+
to_return(:body => "", :status => 200)
|
290
|
+
#allow(Gibbon::Export).to receive(:post).and_return(Struct.new(:body).new(""))
|
273
291
|
|
274
292
|
expect(@gibbon.say_hello(@body)).to eq([])
|
275
293
|
end
|
276
294
|
|
295
|
+
it "should feed API results per row to a given block" do
|
296
|
+
# Fake request
|
297
|
+
stub_request(:post, @url + 'sayHello/').
|
298
|
+
to_return(:body => @returns, :status => 200)
|
299
|
+
|
300
|
+
# Check request url
|
301
|
+
@result = []
|
302
|
+
@gibbon.say_hello(@body) { |res| @result << res }
|
303
|
+
expect(@result).to contain_exactly(@return_items)
|
304
|
+
end
|
305
|
+
|
306
|
+
|
277
307
|
end
|
278
308
|
|
279
309
|
private
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gibbon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Amro Mousa
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-07-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httparty
|
@@ -88,6 +88,7 @@ files:
|
|
88
88
|
- lib/gibbon/export.rb
|
89
89
|
- lib/gibbon/gibbon_error.rb
|
90
90
|
- lib/gibbon/mailchimp_error.rb
|
91
|
+
- lib/gibbon/version.rb
|
91
92
|
- spec/gibbon/gibbon_spec.rb
|
92
93
|
- spec/spec_helper.rb
|
93
94
|
homepage: http://github.com/amro/gibbon
|
@@ -113,7 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
113
114
|
version: '0'
|
114
115
|
requirements: []
|
115
116
|
rubyforge_project: gibbon
|
116
|
-
rubygems_version: 2.
|
117
|
+
rubygems_version: 2.4.6
|
117
118
|
signing_key:
|
118
119
|
specification_version: 4
|
119
120
|
summary: A wrapper for MailChimp API 2.0 and Export API 1.0
|