gibbon 2.2.5 → 3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4264e8ea898f75f9239b7d03d6c5dcb1cadc915d
4
- data.tar.gz: c5e810141d2a9767d6e754128cd2b7d395e62bd1
3
+ metadata.gz: 12a6fecb32704fd28e939c71d68d04b002daa26b
4
+ data.tar.gz: b203c08f25fab5920c4714448709cf16c1297a74
5
5
  SHA512:
6
- metadata.gz: aefbdbd257c1483028840b02bfd1e8952e25f185cdea4cd14b4adc8f6dd928826312605f7d66d264f2856e5a376ecfb841e218488361ab63d400b34bbf9e3d0d
7
- data.tar.gz: 4f789cb640563d3979b5b498852ea8b3552429b17a601eb6c1aab87f9d38c5650b7b55d09cac227fc47f232ea5d940ffdb5682c43c9a332ed642e5ab635d2892
6
+ metadata.gz: 049a905ad6d6ccb68ed25d76e3192ab38e2342405c57aa89070817e79ad64a3d0d635129821b44cc69da778381134f9cada53480644defc8350c9da065851fc2
7
+ data.tar.gz: 15b2cc277b73e3e9b6af78045061d16924cdf677547e82e96ec5c04f37a966f359bbb8e1b589d12f6493e82c5d02b3884dac82328ee92560fab6487d4cf3ce26
@@ -1,6 +1,8 @@
1
1
  language: ruby
2
2
  sudo: false
3
3
  cache: bundler
4
+ before_install:
5
+ - gem install bundler # -v 1.7.14 if a specific version is needed
4
6
  rvm:
5
7
  - 2.0.0
6
8
  - 2.1.5
@@ -1,8 +1,33 @@
1
1
  ## [Unreleased][unreleased]
2
2
 
3
+ ## [3.2.0] - 2017-11-08
4
+ - Force TLS version 1.2
5
+
6
+ ## [3.1.1] - 2017-09-25
7
+ - Fix MailChimpError initialization
8
+
9
+ ## [3.1.0] - 2017-07-27
10
+ - Add back support for Export API until MailChimp stops supporting it
11
+ - Implement `responds_to_missing`
12
+
13
+ ## [3.0.2] - 2017-05-08
14
+ - Fix subtle bug in `symbolize_keys` when parsing error
15
+
16
+ ## [3.0.1] - 2017-01-13
17
+ - Gibbon::Request (API 3.0) now returns a `Gibbon::Response` object that exposes `headers` and the parsed response `body`
18
+ - Remove Export API support (this is deprected after all)
19
+ - Adds `symbolize_keys`, `debug`, and `faraday_adapter` as class vars
20
+ - Bump version to 3.0.1 (not sticking to semver here so folks who downloaded 3.0.0 have a way to easily move forward)
21
+
22
+ ## [3.0.0] - 2017-01-13
23
+ - Gibbon::Request (API 3.0) now returns a `Gibbon::Response` object that exposes `headers` and the parsed response `body`
24
+ - Adds Export API support
25
+ - Adds `symbolize_keys`, `debug`, and `faraday_adapter` as class vars
26
+ - Bump version to 3.0.0 due to breaking API change
27
+
3
28
  ## [2.2.5] - 2016-12-23
4
29
  - Adds open_timeout
5
- - Adds symbolize_keys
30
+ - Adds `symbolize_keys`
6
31
  - Change default timeout from 30 to 60 seconds
7
32
 
8
33
  ## [2.2.4] - 2016-05-21
@@ -54,8 +79,23 @@
54
79
  ## [1.1.4] - 2012-11-04
55
80
  - Fix JSON::ParserError on export calls that return blank results
56
81
 
57
- [unreleased]: https://github.com/amro/gibbon/compare/v2.0.0...HEAD
82
+ [unreleased]: https://github.com/amro/gibbon/compare/v3.1.0...HEAD
83
+ [3.1.0]: https://github.com/amro/gibbon/compare/v3.0.2...v3.1.0
84
+ [3.0.2]: https://github.com/amro/gibbon/compare/v3.0.1...v3.0.2
85
+ [3.0.1]: https://github.com/amro/gibbon/compare/v3.0.0...v3.0.1
86
+ [3.0.0]: https://github.com/amro/gibbon/compare/v2.2.5...v3.0.0
87
+ [2.2.5]: https://github.com/amro/gibbon/compare/v2.2.4...v2.2.5
88
+ [2.2.4]: https://github.com/amro/gibbon/compare/v2.2.2...v2.2.4
89
+ [2.2.3]: https://github.com/amro/gibbon/compare/v2.2.2...v2.2.3
90
+ [2.2.2]: https://github.com/amro/gibbon/compare/v2.2.1...v2.2.2
91
+ [2.2.1]: https://github.com/amro/gibbon/compare/v2.2.0...v2.2.1
92
+ [2.2.0]: https://github.com/amro/gibbon/compare/v2.1.3...v2.2.0
93
+ [2.1.3]: https://github.com/amro/gibbon/compare/v2.1.2...v2.1.3
94
+ [2.1.2]: https://github.com/amro/gibbon/compare/v2.1.1...v2.1.2
95
+ [2.1.1]: https://github.com/amro/gibbon/compare/v2.1.0...v2.1.1
96
+ [2.1.0]: https://github.com/amro/gibbon/compare/v2.0.0...v2.1.0
58
97
  [2.0.0]: https://github.com/amro/gibbon/compare/v1.2.0...v2.0.0
59
98
  [1.2.0]: https://github.com/amro/gibbon/compare/v1.1.5...v1.2.0
60
- [1.1.5]: https://github.com/amro/gibbon/compare/v1.1.5...v1.1.4
99
+ [1.1.6]: https://github.com/amro/gibbon/compare/v1.1.5...v1.1.6
100
+ [1.1.5]: https://github.com/amro/gibbon/compare/v1.1.4...v1.1.5
61
101
  [1.1.4]: https://github.com/amro/gibbon/compare/v1.1.3...v1.1.4
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010-2015 Amro Mousa
1
+ Copyright (c) 2010-2017 Amro Mousa
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -4,23 +4,24 @@ Gibbon is an API wrapper for MailChimp's [API](http://kb.mailchimp.com/api/).
4
4
 
5
5
  [![Build Status](https://secure.travis-ci.org/amro/gibbon.svg)](http://travis-ci.org/amro/gibbon)
6
6
  [![Dependency Status](https://gemnasium.com/amro/gibbon.svg)](https://gemnasium.com/amro/gibbon)
7
- ##Important Notes
8
7
 
9
- Gibbon now targets MailChimp API 3.0, which is substantially different from the previous API. Please use Gibbon 1.1.x if you need to use API 2.0.
8
+ ## Important Notes
10
9
 
11
10
  Please read MailChimp's [Getting Started Guide](http://kb.mailchimp.com/api/article/api-3-overview).
12
11
 
13
- ##Installation
12
+ Gibbon 3.0.0+ returns a `Gibbon::Response` instead of the response body directly. `Gibbon::Response` exposes the parsed response `body` and `headers`.
13
+
14
+ ## Installation
14
15
 
15
16
  $ gem install gibbon
16
17
 
17
- ##Requirements
18
+ ## Requirements
18
19
 
19
20
  A MailChimp account and API key. You can see your API keys [here](http://admin.mailchimp.com/account/api).
20
21
 
21
- ##Usage
22
+ ## Usage
22
23
 
23
- First, create a *one-time use instance* of Gibbon::Request:
24
+ First, create a *one-time use instance* of `Gibbon::Request`:
24
25
 
25
26
  ```ruby
26
27
  gibbon = Gibbon::Request.new(api_key: "your_api_key")
@@ -50,12 +51,14 @@ gibbon.lists.retrieve(headers: {"SomeHeader": "SomeHeaderValue"}, params: {"quer
50
51
 
51
52
  Of course, `body` is only supported on `create`, `update`, and `upsert` calls. Those map to HTTP `POST`, `PATCH`, and `PUT` verbs respectively.
52
53
 
53
- You can set `api_key`, `timeout`, and `open_timeout` globally:
54
+ You can set `api_key`, `timeout`, `open_timeout`, `faraday_adapter`, `proxy`, `symbolize_keys`, `logger`, and `debug` globally:
54
55
 
55
56
  ```ruby
56
57
  Gibbon::Request.api_key = "your_api_key"
57
58
  Gibbon::Request.timeout = 15
58
59
  Gibbon::Request.open_timeout = 15
60
+ Gibbon::Request.symbolize_keys = true
61
+ Gibbon::Request.debug = false
59
62
  ```
60
63
 
61
64
  For example, you could set the values above in an `initializer` file in your `Rails` app (e.g. your\_app/config/initializers/gibbon.rb).
@@ -82,7 +85,7 @@ gibbon = Gibbon::Request.new(api_key: "your_api_key", symbolize_keys: true)
82
85
 
83
86
  MailChimp's [resource documentation](http://kb.mailchimp.com/api/resources) is a list of available resources.
84
87
 
85
- ##Debug Logging
88
+ ## Debug Logging
86
89
 
87
90
  Pass `debug: true` to enable debug logging to STDOUT.
88
91
 
@@ -201,7 +204,7 @@ This will create a new batch job and return a Batch response. The response will
201
204
  gibbon.batches(batch_id).retrieve
202
205
  ```
203
206
 
204
- ###### Response
207
+ ###### Response Body (i.e. `response.body`)
205
208
  ```ruby
206
209
  {
207
210
  "id"=>"0ca62e43cc",
@@ -332,7 +335,7 @@ So how do we get the interest IDs? When you query the API for a specific list me
332
335
  gibbon.lists(list_id).members(member_id).retrieve
333
336
  ```
334
337
 
335
- The response looks someting like this (unrelated things removed):
338
+ The response body (i.e. `response.body`) looks someting like this (unrelated things removed):
336
339
 
337
340
  ```ruby
338
341
  {"id"=>"...", "email_address"=>"...", ..., "interests"=>{"3def637141"=>true, "f7cc4ee841"=>false, "fcdc951b9f"=>false, "3daf3cf27d"=>true, "293a3703ed"=>false, "72370e0d1f"=>false, "d434d21a1c"=>false, "bdb1ff199f"=>false, "a54e78f203"=>false, "c4527fd018"=>false} ...}
@@ -344,7 +347,7 @@ The API returns a map of interest ID to boolean value. Now we to get interest de
344
347
  gibbon.lists(list_id).interest_categories.retrieve
345
348
  ```
346
349
 
347
- To get a list of interest categories. That gives us something like:
350
+ To get a list of interest categories. That gives us something like (again, this is the `response.body`):
348
351
 
349
352
  ```ruby
350
353
  {"list_id"=>"...", "categories"=>[{"list_id"=>"...", "id"=>"0ace7aa498", "title"=>"Food Preferences", ...}] ...}
@@ -396,7 +399,7 @@ gibbon = Gibbon::Request.new(api_key: "your_api_key", faraday_adapter: :net_http
396
399
 
397
400
  ### Migrating from Gibbon 1.x
398
401
 
399
- Gibbon 2.x has different syntax from version 1.x. This is because Gibbon maps to MailChimp's API and because version 3 of the API is quite different from version 2. First, the name of the primary class has changed from `API` to `Request`. And the way you pass an API key during initialization is different. A few examples below.
402
+ Gibbon 2.x+ exposes a different API from version 1.x. This is because Gibbon maps to MailChimp's API and because version 3 of the API is quite different from version 2. First, the name of the primary class has changed from `API` to `Request`. And the way you pass an API key during initialization is different. A few examples below.
400
403
 
401
404
  #### Initialization
402
405
 
@@ -406,7 +409,7 @@ Gibbon 1.x:
406
409
  gibbon = Gibbon::API.new("your_api_key")
407
410
  ```
408
411
 
409
- Gibbon 2.x:
412
+ Gibbon 2.x+:
410
413
 
411
414
  ```ruby
412
415
  gibbon = Gibbon::Request.new(api_key: "your_api_key")
@@ -422,7 +425,7 @@ Gibbon 1.x:
422
425
  gibbon.lists.list
423
426
  ```
424
427
 
425
- Gibbon 2.x:
428
+ Gibbon 2.x+:
426
429
 
427
430
  ```ruby
428
431
  gibbon.lists.retrieve
@@ -436,7 +439,7 @@ Gibbon 1.x:
436
439
  gibbon.lists.members({:id => list_id})
437
440
  ```
438
441
 
439
- Gibbon 2.x:
442
+ Gibbon 2.x+:
440
443
 
441
444
  ```ruby
442
445
  gibbon.lists(list_id).members.retrieve
@@ -450,11 +453,38 @@ Gibbon 1.x:
450
453
  gibbon.lists.subscribe({:id => list_id, :email => {:email => "foo@bar.com"}, :merge_vars => {:FNAME => "Bob", :LNAME => "Smith"}})
451
454
  ```
452
455
 
453
- Gibbon 2.x:
456
+ Gibbon 2.x+:
454
457
 
455
458
  ```ruby
456
459
  gibbon.lists(list_id).members.create(body: {email_address: "foo@bar.com", status: "subscribed", merge_fields: {FNAME: "Bob", LNAME: "Smith"}})
457
460
  ```
461
+ ## Export API 1.0
462
+
463
+ Gibbon 3.0.0+ supports MailChimp's [Export API 1.0](https://apidocs.mailchimp.com/export/1.0/). You can choose to handle the API response all at
464
+ once or line by line by passing a block. To access the Export API with Gibbon, you must first create an instance of `Gibbon::Export`:
465
+
466
+ ```ruby
467
+ export = Gibbon::Export.new(api_key: "your_api_key")
468
+ ```
469
+
470
+ Next, call the method corresponding to the API endpoint you'd like to query:
471
+
472
+ ```ruby
473
+ export.list(id: list_id)
474
+ ```
475
+
476
+ This fetches and returns all of the results at once. Pass a block if you'd like to handle the response as individual lines:
477
+
478
+ ```ruby
479
+ export = Gibbon::Export.new(api_key: "your_api_key", timeout: 1200)
480
+ export.list(id: list_id) do |row|
481
+ puts row
482
+ end
483
+ ```
484
+
485
+ This is useful when handling large sets of data. Setting the `timeout` here is optional, but a high value is recommended given the nature of the Export API. The default timeout is 600 seconds.
486
+
487
+ Gibbon supports all current Export API endpoints: `/list`, `/ecommOrders`, and `/campaignSubscriberActivity`. They're mapped onto Ruby methods with similar names: `list()`, `ecomm_orders()`, and `campaign_subscriber_activity()` respectively. Please see [MailChimp's API documentation](https://developer.mailchimp.com/documentation/mailchimp/guides/how-to-use-the-export-api/) for supported parameters.
458
488
 
459
489
  ## Thanks
460
490
 
@@ -462,5 +492,5 @@ Thanks to everyone who has [contributed](https://github.com/amro/gibbon/contribu
462
492
 
463
493
  ## Copyright
464
494
 
465
- * Copyright (c) 2010-2016 Amro Mousa. See LICENSE.txt for details.
466
- * MailChimp (c) 2001-2016 The Rocket Science Group.
495
+ * Copyright (c) 2010-2017 Amro Mousa. See LICENSE.txt for details.
496
+ * MailChimp (c) 2001-2017 The Rocket Science Group.
@@ -9,8 +9,8 @@ Gem::Specification.new do |s|
9
9
  s.email = ["amromousa@gmail.com"]
10
10
  s.homepage = "http://github.com/amro/gibbon"
11
11
 
12
- s.summary = %q{A wrapper for MailChimp API 3.0}
13
- s.description = %q{A wrapper for MailChimp API 3.0}
12
+ s.summary = %q{A wrapper for MailChimp API 3.0 and Export API}
13
+ s.description = %q{A wrapper for MailChimp API 3.0 and Export API}
14
14
  s.license = "MIT"
15
15
 
16
16
  s.rubyforge_project = "gibbon"
@@ -3,10 +3,13 @@ require 'multi_json'
3
3
  require 'cgi'
4
4
  require 'logger'
5
5
 
6
+ require 'gibbon/gibbon_helpers'
6
7
  require 'gibbon/gibbon_error'
7
8
  require 'gibbon/mailchimp_error'
8
9
  require 'gibbon/request'
9
10
  require 'gibbon/api_request'
11
+ require 'gibbon/response'
12
+ require 'gibbon/export'
10
13
 
11
14
  module Gibbon
12
15
  end
@@ -1,5 +1,7 @@
1
1
  module Gibbon
2
2
  class APIRequest
3
+ include Helpers
4
+
3
5
  def initialize(builder: nil)
4
6
  @request_builder = builder
5
7
  end
@@ -11,7 +13,7 @@ module Gibbon
11
13
  response = self.rest_client.post do |request|
12
14
  configure_request(request: request, params: params, headers: headers, body: MultiJson.dump(body))
13
15
  end
14
- parse_response(response.body)
16
+ parse_response(response)
15
17
  rescue => e
16
18
  handle_error(e)
17
19
  end
@@ -24,7 +26,7 @@ module Gibbon
24
26
  response = self.rest_client.patch do |request|
25
27
  configure_request(request: request, params: params, headers: headers, body: MultiJson.dump(body))
26
28
  end
27
- parse_response(response.body)
29
+ parse_response(response)
28
30
  rescue => e
29
31
  handle_error(e)
30
32
  end
@@ -37,7 +39,7 @@ module Gibbon
37
39
  response = self.rest_client.put do |request|
38
40
  configure_request(request: request, params: params, headers: headers, body: MultiJson.dump(body))
39
41
  end
40
- parse_response(response.body)
42
+ parse_response(response)
41
43
  rescue => e
42
44
  handle_error(e)
43
45
  end
@@ -50,7 +52,7 @@ module Gibbon
50
52
  response = self.rest_client.get do |request|
51
53
  configure_request(request: request, params: params, headers: headers)
52
54
  end
53
- parse_response(response.body)
55
+ parse_response(response)
54
56
  rescue => e
55
57
  handle_error(e)
56
58
  end
@@ -63,7 +65,7 @@ module Gibbon
63
65
  response = self.rest_client.delete do |request|
64
66
  configure_request(request: request, params: params, headers: headers)
65
67
  end
66
- parse_response(response.body)
68
+ parse_response(response)
67
69
  rescue => e
68
70
  handle_error(e)
69
71
  end
@@ -115,8 +117,12 @@ module Gibbon
115
117
 
116
118
  if parsed_response
117
119
  error_params[:body] = parsed_response
118
- error_params[:title] = parsed_response["title"] if parsed_response["title"]
119
- error_params[:detail] = parsed_response["detail"] if parsed_response["detail"]
120
+
121
+ title_key = symbolize_keys ? :title : "title"
122
+ detail_key = symbolize_keys ? :detail : "detail"
123
+
124
+ error_params[:title] = parsed_response[title_key] if parsed_response[title_key]
125
+ error_params[:detail] = parsed_response[detail_key] if parsed_response[detail_key]
120
126
  end
121
127
 
122
128
  end
@@ -140,7 +146,7 @@ module Gibbon
140
146
  end
141
147
 
142
148
  def rest_client
143
- client = Faraday.new(self.api_url, proxy: self.proxy) do |faraday|
149
+ client = Faraday.new(self.api_url, proxy: self.proxy, ssl: { version: "TLSv1_2" }) do |faraday|
144
150
  faraday.response :raise_error
145
151
  faraday.adapter adapter
146
152
  if @request_builder.debug
@@ -151,16 +157,17 @@ module Gibbon
151
157
  client
152
158
  end
153
159
 
154
- def parse_response(response_body)
160
+ def parse_response(response)
155
161
  parsed_response = nil
156
162
 
157
- if response_body && !response_body.empty?
163
+ if response.body && !response.body.empty?
158
164
  begin
159
- parsed_response = MultiJson.load(response_body, symbolize_keys: symbolize_keys)
165
+ headers = response.headers
166
+ body = MultiJson.load(response.body, symbolize_keys: symbolize_keys)
167
+ parsed_response = Response.new(headers: headers, body: body)
160
168
  rescue MultiJson::ParseError
161
- error = MailChimpError.new("Unparseable response: #{response_body}")
162
- error.title = "UNPARSEABLE_RESPONSE"
163
- error.status_code = 500
169
+ error_params = { title: "UNPARSEABLE_RESPONSE", status_code: 500 }
170
+ error = MailChimpError.new("Unparseable response: #{response.body}", error_params)
164
171
  raise error
165
172
  end
166
173
  end
@@ -180,20 +187,8 @@ module Gibbon
180
187
  end
181
188
 
182
189
  def base_api_url
183
- computed_api_endpoint = "https://#{get_data_center_from_api_key}api.mailchimp.com"
190
+ computed_api_endpoint = "https://#{get_data_center_from_api_key(self.api_key)}api.mailchimp.com"
184
191
  "#{self.api_endpoint || computed_api_endpoint}/3.0/"
185
192
  end
186
-
187
- def get_data_center_from_api_key
188
- # Return an empty string for invalid API keys so Gibbon hits the main endpoint
189
- data_center = ""
190
-
191
- if self.api_key && self.api_key["-"]
192
- # Add a period since the data_center is a subdomain and it keeps things dry
193
- data_center = "#{self.api_key.split('-').last}."
194
- end
195
-
196
- data_center
197
- end
198
193
  end
199
194
  end
@@ -0,0 +1,93 @@
1
+ require 'net/https'
2
+
3
+ module Gibbon
4
+ class Export
5
+ include Helpers
6
+
7
+ attr_accessor :api_key, :timeout
8
+
9
+ def initialize(api_key: nil, timeout: nil)
10
+ @api_key = api_key || self.class.api_key
11
+ @timeout = timeout || self.class.timeout || 600
12
+ end
13
+
14
+ def list(params = {}, &block)
15
+ call("list", params, &block)
16
+ end
17
+
18
+ def ecomm_orders(params = {}, &block)
19
+ call("ecommOrders", params, &block)
20
+ end
21
+
22
+ def campaign_subscriber_activity(params = {}, &block)
23
+ call("campaignSubscriberActivity", params, &block)
24
+ end
25
+
26
+ protected
27
+
28
+ def export_api_url
29
+ "https://#{get_data_center_from_api_key(@api_key)}api.mailchimp.com/export/1.0/"
30
+ end
31
+
32
+ def call(method, params = {}, &block)
33
+ rows = []
34
+
35
+ api_url = export_api_url + method + "/"
36
+ params = params.merge({ apikey: @api_key })
37
+ block = Proc.new { |row| rows << row } unless block_given?
38
+
39
+ ensure_api_key(params)
40
+
41
+ url = URI.parse(api_url)
42
+ req = Net::HTTP::Post.new(url.path, initheader = {'Content-Type' => 'application/json'})
43
+ req.body = MultiJson.dump(params)
44
+ Net::HTTP.start(url.host, url.port, read_timeout: @timeout, use_ssl: true, ssl_version: :TLSv1_2) do |http|
45
+ # http://stackoverflow.com/questions/29598196/ruby-net-http-read-body-nethttpokread-body-called-twice-ioerror
46
+ http.request req do |response|
47
+ i = -1
48
+ last = ''
49
+ response.read_body do |chunk|
50
+ next if chunk.nil? or chunk.strip.empty?
51
+ infix = "\n" if last[-1, 1]==']'
52
+ lines, last = try_parse_line("#{last}#{infix}#{chunk}")
53
+ lines.each { |line| block.call(line, i += 1) }
54
+ end
55
+ block.call(parse_line(last), i += 1) unless last.nil? or last.empty?
56
+ end
57
+ end
58
+ rows unless block_given?
59
+ end
60
+
61
+ def try_parse_line(res)
62
+ lines = res.split("\n")
63
+ last = lines.pop || ''
64
+ lines.map! { |line| parse_line(line) }
65
+ [lines.compact, last]
66
+ rescue MultiJson::ParseError
67
+ [[], last]
68
+ end
69
+
70
+
71
+ def parse_line(line)
72
+ parsed_response = MultiJson.load(line)
73
+ rescue MultiJson::ParseError
74
+ return []
75
+ end
76
+
77
+ private
78
+
79
+ def ensure_api_key(params)
80
+ unless params[:apikey] && (get_data_center_from_api_key(params[:apikey]) != "")
81
+ raise Gibbon::GibbonError, "You must set an api_key prior to making a call"
82
+ end
83
+ end
84
+
85
+ class << self
86
+ attr_accessor :api_key, :timeout
87
+
88
+ def method_missing(sym, *args, &block)
89
+ new(api_key: self.api_key, timeout: self.timeout).send(sym, *args, &block)
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,15 @@
1
+ module Gibbon
2
+ module Helpers
3
+ def get_data_center_from_api_key(api_key)
4
+ # Return an empty string for invalid API keys so Gibbon hits the main endpoint
5
+ data_center = ""
6
+
7
+ if api_key && api_key["-"]
8
+ # Add a period since the data_center is a subdomain and it keeps things dry
9
+ data_center = "#{api_key.split('-').last}."
10
+ end
11
+
12
+ data_center
13
+ end
14
+ end
15
+ end
@@ -14,9 +14,9 @@ module Gibbon
14
14
  @open_timeout = open_timeout || self.class.open_timeout || DEFAULT_OPEN_TIMEOUT
15
15
  @proxy = proxy || self.class.proxy || ENV['MAILCHIMP_PROXY']
16
16
  @faraday_adapter = faraday_adapter || Faraday.default_adapter
17
- @symbolize_keys = symbolize_keys
17
+ @symbolize_keys = symbolize_keys || self.class.symbolize_keys || false
18
+ @debug = debug || self.class.debug || false
18
19
  @logger = logger || self.class.logger || ::Logger.new(STDOUT)
19
- @debug = debug
20
20
  end
21
21
 
22
22
  def method_missing(method, *args)
@@ -27,6 +27,10 @@ module Gibbon
27
27
  self
28
28
  end
29
29
 
30
+ def respond_to_missing?(method_name, include_private = false)
31
+ true
32
+ end
33
+
30
34
  def send(*args)
31
35
  if args.length == 0
32
36
  method_missing(:send, args)
@@ -76,10 +80,14 @@ module Gibbon
76
80
  end
77
81
 
78
82
  class << self
79
- attr_accessor :api_key, :timeout, :open_timeout, :api_endpoint, :proxy, :logger
83
+ attr_accessor :api_key, :timeout, :open_timeout, :api_endpoint, :proxy, :faraday_adapter, :symbolize_keys, :debug, :logger
80
84
 
81
85
  def method_missing(sym, *args, &block)
82
- new(api_key: self.api_key, api_endpoint: self.api_endpoint, timeout: self.timeout, open_timeout: self.open_timeout, proxy: self.proxy, logger: self.logger).send(sym, *args, &block)
86
+ new(api_key: self.api_key, api_endpoint: self.api_endpoint, timeout: self.timeout, open_timeout: self.open_timeout, faraday_adapter: self.faraday_adapter, symbolize_keys: self.symbolize_keys, debug: self.debug, proxy: self.proxy, logger: self.logger).send(sym, *args, &block)
87
+ end
88
+
89
+ def respond_to_missing?(method_name, include_private = false)
90
+ true
83
91
  end
84
92
  end
85
93
  end
@@ -0,0 +1,10 @@
1
+ module Gibbon
2
+ class Response
3
+ attr_accessor :body, :headers
4
+
5
+ def initialize(body: {}, headers: {})
6
+ @body = body
7
+ @headers = headers
8
+ end
9
+ end
10
+ end
@@ -1,3 +1,3 @@
1
1
  module Gibbon
2
- VERSION = "2.2.5"
2
+ VERSION = "3.2.0"
3
3
  end
@@ -42,5 +42,19 @@ describe Gibbon::APIRequest do
42
42
  expect(boom.raw_body).to eq "A non JSON response"
43
43
  end
44
44
  end
45
+
46
+ context "when symbolize_keys is true" do
47
+ it "sets title and detail on the error params" do
48
+ response_values = {:status => 422, :headers => {}, :body => '{"title": "foo", "detail": "bar"}'}
49
+ exception = Faraday::Error::ClientError.new("the server responded with status 422", response_values)
50
+ api_request = Gibbon::APIRequest.new(builder: Gibbon::Request.new(symbolize_keys: true))
51
+ begin
52
+ api_request.send :handle_error, exception
53
+ rescue => boom
54
+ expect(boom.title).to eq "foo"
55
+ expect(boom.detail).to eq "bar"
56
+ end
57
+ end
58
+ end
45
59
  end
46
60
  end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+ require 'webmock/rspec'
3
+
4
+ describe Gibbon::Export do
5
+ before do
6
+ Gibbon::Export.send(:public, *Gibbon::Export.protected_instance_methods)
7
+ @export = Gibbon::Export.new
8
+ end
9
+
10
+ it "doesn't allow empty api key" do
11
+ expect {@export.list(id: "123456")}.to raise_error(Gibbon::GibbonError)
12
+ end
13
+
14
+ it "doesn't allow api key without data center" do
15
+ @api_key = "123"
16
+ @export.api_key = @api_key
17
+ expect {@export.list(id: "123456")}.to raise_error(Gibbon::GibbonError)
18
+ end
19
+
20
+ it "sets correct endpoint from api key" do
21
+ @api_key = "TESTKEY-us1"
22
+ @export.api_key = @api_key
23
+ expect(@export.export_api_url).to eq("https://us1.api.mailchimp.com/export/1.0/")
24
+ end
25
+
26
+ it "sets correct timeout" do
27
+ @api_key = "TESTKEY-us1"
28
+ @export.api_key = @api_key
29
+ @export.timeout = 9
30
+ expect(@export.timeout).to eq(9)
31
+ end
32
+ end
@@ -102,6 +102,10 @@ describe Gibbon do
102
102
  expect(@gibbon.symbolize_keys).to be true
103
103
  end
104
104
 
105
+ it "sets symbolize_keys in the constructor" do
106
+ @gibbon = Gibbon::Request.new(symbolize_keys: true)
107
+ expect(@gibbon.symbolize_keys).to be true
108
+ end
105
109
  it "debug false by default" do
106
110
  @gibbon = Gibbon::Request.new
107
111
  expect(@gibbon.debug).to be false
@@ -123,7 +127,6 @@ describe Gibbon do
123
127
  expect(@gibbon.logger).to be_a Logger
124
128
  end
125
129
 
126
-
127
130
  end
128
131
 
129
132
  describe "build api url" do
@@ -131,7 +134,6 @@ describe Gibbon do
131
134
  Gibbon::APIRequest.send(:public, *Gibbon::APIRequest.protected_instance_methods)
132
135
 
133
136
  @gibbon = Gibbon::Request.new
134
- @url = "https://api.mailchimp.com/3.0/lists/"
135
137
  end
136
138
 
137
139
  it "doesn't allow empty api key" do
@@ -170,6 +172,10 @@ describe Gibbon do
170
172
  Gibbon::Request.timeout = 15
171
173
  Gibbon::Request.api_endpoint = 'https://us6.api.mailchimp.com'
172
174
  Gibbon::Request.logger = logger
175
+ Gibbon::Request.proxy = "http://1234.com"
176
+ Gibbon::Request.symbolize_keys = true
177
+ Gibbon::Request.faraday_adapter = :net_http
178
+ Gibbon::Request.debug = true
173
179
  end
174
180
 
175
181
  after do
@@ -177,6 +183,10 @@ describe Gibbon do
177
183
  Gibbon::Request.timeout = nil
178
184
  Gibbon::Request.api_endpoint = nil
179
185
  Gibbon::Request.logger = nil
186
+ Gibbon::Request.proxy = nil
187
+ Gibbon::Request.symbolize_keys = nil
188
+ Gibbon::Request.faraday_adapter = nil
189
+ Gibbon::Request.debug = nil
180
190
  end
181
191
 
182
192
  it "set api key on new instances" do
@@ -192,8 +202,33 @@ describe Gibbon do
192
202
  expect(Gibbon::Request.new.api_endpoint).to eq(Gibbon::Request.api_endpoint)
193
203
  end
194
204
 
205
+ it "set proxy on new instances" do
206
+ expect(Gibbon::Request.new.proxy).to eq(Gibbon::Request.proxy)
207
+ end
208
+
209
+ it "set symbolize_keys on new instances" do
210
+ expect(Gibbon::Request.new.symbolize_keys).to eq(Gibbon::Request.symbolize_keys)
211
+ end
212
+
213
+ it "set debug on new instances" do
214
+ expect(Gibbon::Request.new.debug).to eq(Gibbon::Request.debug)
215
+ end
216
+
217
+ it "set faraday_adapter on new instances" do
218
+ expect(Gibbon::Request.new.faraday_adapter).to eq(Gibbon::Request.faraday_adapter)
219
+ end
220
+
195
221
  it "set logger on new instances" do
196
222
  expect(Gibbon::Request.new.logger).to eq(logger)
197
223
  end
198
224
  end
225
+
226
+ describe "missing methods" do
227
+ it "respond to .method call on class" do
228
+ expect(Gibbon::Request.method(:lists)).to be_a(Method)
229
+ end
230
+ it "respond to .method call on instance" do
231
+ expect(Gibbon::Request.new.method(:lists)).to be_a(Method)
232
+ end
233
+ end
199
234
  end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe Gibbon::MailChimpError do
4
+ let(:message) { 'Foo' }
5
+ let(:params) do
6
+ {
7
+ title: 'error_title',
8
+ detail: 'error_detail',
9
+ body: 'error_body',
10
+ raw_body: 'error_raw_body',
11
+ status_code: 'error_status_code'
12
+ }
13
+ end
14
+
15
+ before do
16
+ @gibbon = Gibbon::MailChimpError.new(message, params)
17
+ end
18
+
19
+ it "adds the error params to the error message" do
20
+ expected_message = "Foo " \
21
+ "@title=\"error_title\", " \
22
+ "@detail=\"error_detail\", " \
23
+ "@body=\"error_body\", " \
24
+ "@raw_body=\"error_raw_body\", " \
25
+ "@status_code=\"error_status_code\""
26
+
27
+ expect(@gibbon.message).to eq(expected_message)
28
+ end
29
+
30
+ it 'sets the title attribute' do
31
+ expect(@gibbon.title).to eq(params[:title])
32
+ end
33
+
34
+ it 'sets the detail attribute' do
35
+ expect(@gibbon.detail).to eq(params[:detail])
36
+ end
37
+
38
+ it 'sets the body attribute' do
39
+ expect(@gibbon.body).to eq(params[:body])
40
+ end
41
+
42
+ it 'sets the raw_body attribute' do
43
+ expect(@gibbon.raw_body).to eq(params[:raw_body])
44
+ end
45
+
46
+ it 'sets the status_code attribute' do
47
+ expect(@gibbon.status_code).to eq(params[:status_code])
48
+ end
49
+ end
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: 2.2.5
4
+ version: 3.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: 2016-12-24 00:00:00.000000000 Z
11
+ date: 2017-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -80,7 +80,7 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: 1.21.0
83
- description: A wrapper for MailChimp API 3.0
83
+ description: A wrapper for MailChimp API 3.0 and Export API
84
84
  email:
85
85
  - amromousa@gmail.com
86
86
  executables: []
@@ -98,12 +98,17 @@ files:
98
98
  - gibbon.gemspec
99
99
  - lib/gibbon.rb
100
100
  - lib/gibbon/api_request.rb
101
+ - lib/gibbon/export.rb
101
102
  - lib/gibbon/gibbon_error.rb
103
+ - lib/gibbon/gibbon_helpers.rb
102
104
  - lib/gibbon/mailchimp_error.rb
103
105
  - lib/gibbon/request.rb
106
+ - lib/gibbon/response.rb
104
107
  - lib/gibbon/version.rb
105
108
  - spec/gibbon/api_request_spec.rb
109
+ - spec/gibbon/export_spec.rb
106
110
  - spec/gibbon/gibbon_spec.rb
111
+ - spec/gibbon/mailchimp_error_spec.rb
107
112
  - spec/gibbon/upsert_spec.rb
108
113
  - spec/spec_helper.rb
109
114
  homepage: http://github.com/amro/gibbon
@@ -129,9 +134,11 @@ rubyforge_project: gibbon
129
134
  rubygems_version: 2.4.6
130
135
  signing_key:
131
136
  specification_version: 4
132
- summary: A wrapper for MailChimp API 3.0
137
+ summary: A wrapper for MailChimp API 3.0 and Export API
133
138
  test_files:
134
139
  - spec/gibbon/api_request_spec.rb
140
+ - spec/gibbon/export_spec.rb
135
141
  - spec/gibbon/gibbon_spec.rb
142
+ - spec/gibbon/mailchimp_error_spec.rb
136
143
  - spec/gibbon/upsert_spec.rb
137
144
  - spec/spec_helper.rb