gibbon 2.2.4 → 2.2.5

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: 50f6e393e4d3bca4e56673db5f615de6f45008d4
4
- data.tar.gz: 36eb3eee9d7a618fd29a4d5de4d0f8facd3a7563
3
+ metadata.gz: 4264e8ea898f75f9239b7d03d6c5dcb1cadc915d
4
+ data.tar.gz: c5e810141d2a9767d6e754128cd2b7d395e62bd1
5
5
  SHA512:
6
- metadata.gz: 97c4755405474f78cb0674f4caf23389786d22aafa351b7ba2fc08e4666ada7f33c6fa8709d071ee2d83b451a5b6426748993593f40a7705c2a63abb8fc7c1f9
7
- data.tar.gz: e426ee592429a2fe4c919ed11f2ecbdef11fcb5017fd721712a4c5beff67cd3e7a59fac98de95c085be1a700a994cb8973222c8b03b5bade6b4cbaccb9f29fbe
6
+ metadata.gz: aefbdbd257c1483028840b02bfd1e8952e25f185cdea4cd14b4adc8f6dd928826312605f7d66d264f2856e5a376ecfb841e218488361ab63d400b34bbf9e3d0d
7
+ data.tar.gz: 4f789cb640563d3979b5b498852ea8b3552429b17a601eb6c1aab87f9d38c5650b7b55d09cac227fc47f232ea5d940ffdb5682c43c9a332ed642e5ab635d2892
@@ -4,5 +4,5 @@ cache: bundler
4
4
  rvm:
5
5
  - 2.0.0
6
6
  - 2.1.5
7
- - 2.2.0
8
- - rbx-2
7
+ - 2.2.2
8
+ - 2.3.3
@@ -1,5 +1,10 @@
1
1
  ## [Unreleased][unreleased]
2
2
 
3
+ ## [2.2.5] - 2016-12-23
4
+ - Adds open_timeout
5
+ - Adds symbolize_keys
6
+ - Change default timeout from 30 to 60 seconds
7
+
3
8
  ## [2.2.4] - 2016-05-21
4
9
  - Add debug logging
5
10
 
@@ -20,22 +20,27 @@ A MailChimp account and API key. You can see your API keys [here](http://admin.m
20
20
 
21
21
  ##Usage
22
22
 
23
- First, create an instance Gibbon::Request:
23
+ First, create a *one-time use instance* of Gibbon::Request:
24
24
 
25
25
  ```ruby
26
26
  gibbon = Gibbon::Request.new(api_key: "your_api_key")
27
27
  ```
28
28
 
29
- You can set an individual request's timeout like this:
29
+ ***Note*** Only reuse instances of Gibbon after terminating a call with a verb, which makes a request. Requests are light weight objects that update an internal path based on your call chain. When you terminate a call chain with a verb, a request instance makes a request an resets the path.
30
+
31
+ You can set an individual request's `timeout` and `open_timeout` like this:
30
32
 
31
33
  ```ruby
32
- gibbon.timeout = 10
34
+ gibbon.timeout = 30
35
+ gibbon.open_timeout = 30
33
36
  ```
34
37
 
38
+ You can read about `timeout` and `open_timeout` in the [Net::HTTP](https://ruby-doc.org/stdlib-2.3.3/libdoc/net/http/rdoc/Net/HTTP.html) doc.
39
+
35
40
  Now you can make requests using the resources defined in [MailChimp's docs](http://kb.mailchimp.com/api/resources). Resource IDs
36
41
  are specified inline and a `CRUD` (`create`, `retrieve`, `update`, `upsert`, or `delete`) verb initiates the request. `upsert` lets you update a record, if it exists, or insert it otherwise where supported by MailChimp's API.
37
42
 
38
- *Please note that `upsert` requires Gibbon version 2.1.0 or newer!*
43
+ ***Note*** `upsert` requires Gibbon version 2.1.0 or newer!
39
44
 
40
45
  You can specify `headers`, `params`, and `body` when calling a `CRUD` method. For example:
41
46
 
@@ -45,11 +50,12 @@ gibbon.lists.retrieve(headers: {"SomeHeader": "SomeHeaderValue"}, params: {"quer
45
50
 
46
51
  Of course, `body` is only supported on `create`, `update`, and `upsert` calls. Those map to HTTP `POST`, `PATCH`, and `PUT` verbs respectively.
47
52
 
48
- You can set `api_key` and `timeout` globally:
53
+ You can set `api_key`, `timeout`, and `open_timeout` globally:
49
54
 
50
55
  ```ruby
51
56
  Gibbon::Request.api_key = "your_api_key"
52
57
  Gibbon::Request.timeout = 15
58
+ Gibbon::Request.open_timeout = 15
53
59
  ```
54
60
 
55
61
  For example, you could set the values above in an `initializer` file in your `Rails` app (e.g. your\_app/config/initializers/gibbon.rb).
@@ -68,6 +74,12 @@ gibbon = Gibbon::Request.new
68
74
 
69
75
  ***Note*** Substitute an underscore if a resource name contains a hyphen.
70
76
 
77
+ Pass `symbolize_keys: true` to use symbols (instead of strings) as hash keys in API responses.
78
+
79
+ ```ruby
80
+ gibbon = Gibbon::Request.new(api_key: "your_api_key", symbolize_keys: true)
81
+ ```
82
+
71
83
  MailChimp's [resource documentation](http://kb.mailchimp.com/api/resources) is a list of available resources.
72
84
 
73
85
  ##Debug Logging
@@ -78,6 +90,20 @@ Pass `debug: true` to enable debug logging to STDOUT.
78
90
  gibbon = Gibbon::Request.new(api_key: "your_api_key", debug: true)
79
91
  ```
80
92
 
93
+ ### Custom logger
94
+
95
+ Ruby `Logger.new` is used by default, but it can be overrided using:
96
+
97
+ ```ruby
98
+ gibbon = Gibbon::Request.new(api_key: "your_api_key", debug: true, logger: MyLogger.new)
99
+ ```
100
+
101
+ Logger can be also set by globally:
102
+
103
+ ```ruby
104
+ Gibbon::Request.logger = MyLogger.new
105
+ ```
106
+
81
107
  ## Examples
82
108
 
83
109
  ### Lists
@@ -117,13 +143,13 @@ gibbon.lists(list_id).members.retrieve(params: {"count": "50"})
117
143
  And to retrieve the next 50 members:
118
144
 
119
145
  ```ruby
120
- gibbon.lists(list_id).members.retrieve(params: {"count": "50", "offset: "50"})
146
+ gibbon.lists(list_id).members.retrieve(params: {"count": "50", "offset": "50"})
121
147
  ```
122
148
 
123
149
  And to retrieve only subscribed members
124
150
 
125
151
  ```ruby
126
- gibbon.lists(list_id).members.retrieve(params: {"count": "50", "offset: "50", "status": "subscribed"})
152
+ gibbon.lists(list_id).members.retrieve(params: {"count": "50", "offset": "50", "status": "subscribed"})
127
153
  ```
128
154
 
129
155
  Subscribe a member to a list:
@@ -144,6 +170,12 @@ You can also unsubscribe a member from a list:
144
170
  gibbon.lists(list_id).members(lower_case_md5_hashed_email_address).update(body: { status: "unsubscribed" })
145
171
  ```
146
172
 
173
+ Get a specific member's information (open/click rates etc.) from MailChimp:
174
+
175
+ ```ruby
176
+ gibbon.lists(list_id).members(lower_case_md5_hashed_email_address).retrieve
177
+ ```
178
+
147
179
  ### Batch Operations
148
180
 
149
181
  Any API call that can be made directly can also be organized into batch operations. Performing batch operations requires you to generate a hash for each individual API call and pass them as an `Array` to the Batch endpoint.
@@ -183,7 +215,7 @@ gibbon.batches(batch_id).retrieve
183
215
  }
184
216
  ```
185
217
 
186
- **NOTE** This response truncated for brevity. Reference the MailChimp
218
+ ***Note*** This response truncated for brevity. Reference the MailChimp
187
219
  [API documentation for Batch Operations](http://developer.mailchimp.com/documentation/mailchimp/reference/batches/) for more details.
188
220
 
189
221
  ### Fields
@@ -266,6 +298,18 @@ Send a campaign:
266
298
  gibbon.campaigns(campaign_id).actions.send.create
267
299
  ```
268
300
 
301
+ Schedule a campaign:
302
+
303
+ ```ruby
304
+ body = {
305
+ schedule_time: "2016-06-27 20:00:00"
306
+ }
307
+ ```
308
+
309
+ ```ruby
310
+ gibbon.campaigns(campaign_id).actions.schedule.create(body: body)
311
+ ```
312
+
269
313
  ### Interests
270
314
 
271
315
  Interests are a little more complicated than other parts of the API, so here's an example of how you would set interests during at subscription time or update them later. The ID of the interests you want to opt in or out of must be known ahead of time so an example of how to find interest IDs is also included.
@@ -273,7 +317,7 @@ Interests are a little more complicated than other parts of the API, so here's a
273
317
  Subscribing a member to a list with specific interests up front:
274
318
 
275
319
  ```ruby
276
- g.lists(list_id).members.create(body: {email_address: user_email_address, status: "subscribed", interests: {some_interest_id: true, another_interest_id: true}})
320
+ gibbon.lists(list_id).members.create(body: {email_address: user_email_address, status: "subscribed", interests: {some_interest_id: true, another_interest_id: true}})
277
321
  ```
278
322
 
279
323
  Updating a list member's interests:
@@ -285,7 +329,7 @@ gibbon.lists(list_id).members(member_id).update(body: {interests: {some_interest
285
329
  So how do we get the interest IDs? When you query the API for a specific list member's information:
286
330
 
287
331
  ```ruby
288
- g.lists(list_id).members(member_id).retrieve
332
+ gibbon.lists(list_id).members(member_id).retrieve
289
333
  ```
290
334
 
291
335
  The response looks someting like this (unrelated things removed):
@@ -297,7 +341,7 @@ The response looks someting like this (unrelated things removed):
297
341
  The API returns a map of interest ID to boolean value. Now we to get interest details so we know what these interest IDs map to. Looking at [this doc page](http://kb.mailchimp.com/api/resources/lists/interest-categories/interests/lists-interests-collection), we need to do this:
298
342
 
299
343
  ```ruby
300
- g.lists(list_id).interest_categories.retrieve
344
+ gibbon.lists(list_id).interest_categories.retrieve
301
345
  ```
302
346
 
303
347
  To get a list of interest categories. That gives us something like:
@@ -309,7 +353,7 @@ To get a list of interest categories. That gives us something like:
309
353
  In this case, we're interested in the ID of the "Food Preferences" interest, which is `0ace7aa498`. Now we can fetch the details for this interest group:
310
354
 
311
355
  ```ruby
312
- g.lists(list_id).interest_categories("0ace7aa498").interests.retrieve
356
+ gibbon.lists(list_id).interest_categories("0ace7aa498").interests.retrieve
313
357
  ```
314
358
 
315
359
  That response gives the interest data, including the ID for the interests themselves, which we can use to update a list member's interests or set them when we call the API to subscribe her or him to a list.
@@ -323,7 +367,7 @@ available depending on the nature of the error. For example:
323
367
 
324
368
  ```ruby
325
369
  begin
326
- gibbon.lists(list_id)members.create(body: body)
370
+ gibbon.lists(list_id).members.create(body: body)
327
371
  rescue Gibbon::MailChimpError => e
328
372
  puts "Houston, we have a problem: #{e.message} - #{e.raw_body}"
329
373
  end
@@ -13,8 +13,6 @@ Gem::Specification.new do |s|
13
13
  s.description = %q{A wrapper for MailChimp API 3.0}
14
14
  s.license = "MIT"
15
15
 
16
- s.post_install_message = "IMPORTANT: Gibbon now targets MailChimp API 3.0, which is very different from API 2.0. Use Gibbon 1.x if you need to target API 2.0."
17
-
18
16
  s.rubyforge_project = "gibbon"
19
17
 
20
18
  s.files = `git ls-files`.split("\n")
@@ -27,7 +25,7 @@ Gem::Specification.new do |s|
27
25
  s.add_dependency('multi_json', '>= 1.11.0')
28
26
 
29
27
  s.add_development_dependency 'rake'
30
- s.add_development_dependency "rspec", "3.2.0"
28
+ s.add_development_dependency "rspec", "3.5.0"
31
29
  s.add_development_dependency 'webmock', '~> 1.21.0'
32
30
 
33
31
  end
@@ -1,6 +1,7 @@
1
1
  require 'faraday'
2
2
  require 'multi_json'
3
3
  require 'cgi'
4
+ require 'logger'
4
5
 
5
6
  require 'gibbon/gibbon_error'
6
7
  require 'gibbon/mailchimp_error'
@@ -85,6 +85,10 @@ module Gibbon
85
85
  @request_builder.timeout
86
86
  end
87
87
 
88
+ def open_timeout
89
+ @request_builder.open_timeout
90
+ end
91
+
88
92
  def proxy
89
93
  @request_builder.proxy
90
94
  end
@@ -93,6 +97,10 @@ module Gibbon
93
97
  @request_builder.faraday_adapter
94
98
  end
95
99
 
100
+ def symbolize_keys
101
+ @request_builder.symbolize_keys
102
+ end
103
+
96
104
  # Helpers
97
105
 
98
106
  def handle_error(error)
@@ -102,8 +110,8 @@ module Gibbon
102
110
  if error.is_a?(Faraday::Error::ClientError) && error.response
103
111
  error_params[:status_code] = error.response[:status]
104
112
  error_params[:raw_body] = error.response[:body]
105
-
106
- parsed_response = MultiJson.load(error.response[:body])
113
+
114
+ parsed_response = MultiJson.load(error.response[:body], symbolize_keys: symbolize_keys)
107
115
 
108
116
  if parsed_response
109
117
  error_params[:body] = parsed_response
@@ -127,6 +135,7 @@ module Gibbon
127
135
  request.headers.merge!(headers) if headers
128
136
  request.body = body if body
129
137
  request.options.timeout = self.timeout
138
+ request.options.open_timeout = self.open_timeout
130
139
  end
131
140
  end
132
141
 
@@ -135,7 +144,7 @@ module Gibbon
135
144
  faraday.response :raise_error
136
145
  faraday.adapter adapter
137
146
  if @request_builder.debug
138
- faraday.response :logger, ::Logger.new(STDOUT), bodies: true
147
+ faraday.response :logger, @request_builder.logger, bodies: true
139
148
  end
140
149
  end
141
150
  client.basic_auth('apikey', self.api_key)
@@ -147,7 +156,7 @@ module Gibbon
147
156
 
148
157
  if response_body && !response_body.empty?
149
158
  begin
150
- parsed_response = MultiJson.load(response_body)
159
+ parsed_response = MultiJson.load(response_body, symbolize_keys: symbolize_keys)
151
160
  rescue MultiJson::ParseError
152
161
  error = MailChimpError.new("Unparseable response: #{response_body}")
153
162
  error.title = "UNPARSEABLE_RESPONSE"
@@ -1,17 +1,21 @@
1
1
  module Gibbon
2
2
  class Request
3
- attr_accessor :api_key, :api_endpoint, :timeout, :proxy, :faraday_adapter, :debug
3
+ attr_accessor :api_key, :api_endpoint, :timeout, :open_timeout, :proxy, :faraday_adapter, :symbolize_keys, :debug, :logger
4
4
 
5
- DEFAULT_TIMEOUT = 30
5
+ DEFAULT_TIMEOUT = 60
6
+ DEFAULT_OPEN_TIMEOUT = 60
6
7
 
7
- def initialize(api_key: nil, api_endpoint: nil, timeout: nil, proxy: nil, faraday_adapter: nil, debug: false)
8
+ def initialize(api_key: nil, api_endpoint: nil, timeout: nil, open_timeout: nil, proxy: nil, faraday_adapter: nil, symbolize_keys: false, debug: false, logger: nil)
8
9
  @path_parts = []
9
10
  @api_key = api_key || self.class.api_key || ENV['MAILCHIMP_API_KEY']
10
11
  @api_key = @api_key.strip if @api_key
11
12
  @api_endpoint = api_endpoint || self.class.api_endpoint
12
13
  @timeout = timeout || self.class.timeout || DEFAULT_TIMEOUT
14
+ @open_timeout = open_timeout || self.class.open_timeout || DEFAULT_OPEN_TIMEOUT
13
15
  @proxy = proxy || self.class.proxy || ENV['MAILCHIMP_PROXY']
14
16
  @faraday_adapter = faraday_adapter || Faraday.default_adapter
17
+ @symbolize_keys = symbolize_keys
18
+ @logger = logger || self.class.logger || ::Logger.new(STDOUT)
15
19
  @debug = debug
16
20
  end
17
21
 
@@ -72,10 +76,10 @@ module Gibbon
72
76
  end
73
77
 
74
78
  class << self
75
- attr_accessor :api_key, :timeout, :api_endpoint, :proxy
79
+ attr_accessor :api_key, :timeout, :open_timeout, :api_endpoint, :proxy, :logger
76
80
 
77
81
  def method_missing(sym, *args, &block)
78
- new(api_key: self.api_key, api_endpoint: self.api_endpoint, timeout: self.timeout, proxy: self.proxy).send(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)
79
83
  end
80
84
  end
81
85
  end
@@ -1,3 +1,3 @@
1
1
  module Gibbon
2
- VERSION = "2.2.4"
2
+ VERSION = "2.2.5"
3
3
  end
@@ -34,7 +34,7 @@ describe Gibbon::APIRequest do
34
34
  it "includes status and raw body even when json can't be parsed" do
35
35
  response_values = {:status => 503, :headers => {}, :body => 'A non JSON response'}
36
36
  exception = Faraday::Error::ClientError.new("the server responded with status 503", response_values)
37
- api_request = Gibbon::APIRequest.new
37
+ api_request = Gibbon::APIRequest.new(builder: Gibbon::Request)
38
38
  begin
39
39
  api_request.send :handle_error, exception
40
40
  rescue => boom
@@ -39,6 +39,13 @@ describe Gibbon do
39
39
  expect(timeout).to eq(@gibbon.timeout)
40
40
  end
41
41
 
42
+ it "sets the open_timeout and get" do
43
+ @gibbon = Gibbon::Request.new
44
+ open_timeout = 30
45
+ @gibbon.open_timeout = open_timeout
46
+ expect(open_timeout).to eq(@gibbon.open_timeout)
47
+ end
48
+
42
49
  it "timeout properly passed to APIRequest" do
43
50
  @gibbon = Gibbon::Request.new
44
51
  timeout = 30
@@ -47,6 +54,14 @@ describe Gibbon do
47
54
  expect(timeout).to eq(@request.timeout)
48
55
  end
49
56
 
57
+ it "timeout properly based on open_timeout passed to APIRequest" do
58
+ @gibbon = Gibbon::Request.new
59
+ open_timeout = 30
60
+ @gibbon.open_timeout = open_timeout
61
+ @request = Gibbon::APIRequest.new(builder: @gibbon)
62
+ expect(open_timeout).to eq(@request.open_timeout)
63
+ end
64
+
50
65
  it "detect api endpoint from initializer parameters" do
51
66
  api_endpoint = 'https://us6.api.mailchimp.com'
52
67
  @gibbon = Gibbon::Request.new(api_key: @api_key, api_endpoint: api_endpoint)
@@ -77,6 +92,16 @@ describe Gibbon do
77
92
  expect(@gibbon.faraday_adapter).to eq(adapter)
78
93
  end
79
94
 
95
+ it "symbolize_keys false by default" do
96
+ @gibbon = Gibbon::Request.new
97
+ expect(@gibbon.symbolize_keys).to be false
98
+ end
99
+
100
+ it "sets symbolize_keys in the constructor" do
101
+ @gibbon = Gibbon::Request.new(symbolize_keys: true)
102
+ expect(@gibbon.symbolize_keys).to be true
103
+ end
104
+
80
105
  it "debug false by default" do
81
106
  @gibbon = Gibbon::Request.new
82
107
  expect(@gibbon.debug).to be false
@@ -86,6 +111,19 @@ describe Gibbon do
86
111
  @gibbon = Gibbon::Request.new(debug: true)
87
112
  expect(@gibbon.debug).to be true
88
113
  end
114
+
115
+ it "sets logger in constructor" do
116
+ logger = double(:logger)
117
+ @gibbon = Gibbon::Request.new(logger: logger)
118
+ expect(@gibbon.logger).to eq(logger)
119
+ end
120
+
121
+ it "is a Logger instance by default" do
122
+ @gibbon = Gibbon::Request.new
123
+ expect(@gibbon.logger).to be_a Logger
124
+ end
125
+
126
+
89
127
  end
90
128
 
91
129
  describe "build api url" do
@@ -125,16 +163,20 @@ describe Gibbon do
125
163
  end
126
164
 
127
165
  describe "class variables" do
166
+ let(:logger) { double(:logger) }
167
+
128
168
  before do
129
169
  Gibbon::Request.api_key = "123-us1"
130
170
  Gibbon::Request.timeout = 15
131
171
  Gibbon::Request.api_endpoint = 'https://us6.api.mailchimp.com'
172
+ Gibbon::Request.logger = logger
132
173
  end
133
174
 
134
175
  after do
135
176
  Gibbon::Request.api_key = nil
136
177
  Gibbon::Request.timeout = nil
137
178
  Gibbon::Request.api_endpoint = nil
179
+ Gibbon::Request.logger = nil
138
180
  end
139
181
 
140
182
  it "set api key on new instances" do
@@ -149,5 +191,9 @@ describe Gibbon do
149
191
  expect(Gibbon::Request.api_endpoint).not_to be_nil
150
192
  expect(Gibbon::Request.new.api_endpoint).to eq(Gibbon::Request.api_endpoint)
151
193
  end
194
+
195
+ it "set logger on new instances" do
196
+ expect(Gibbon::Request.new.logger).to eq(logger)
197
+ end
152
198
  end
153
199
  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.4
4
+ version: 2.2.5
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-05-22 00:00:00.000000000 Z
11
+ date: 2016-12-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - '='
60
60
  - !ruby/object:Gem::Version
61
- version: 3.2.0
61
+ version: 3.5.0
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - '='
67
67
  - !ruby/object:Gem::Version
68
- version: 3.2.0
68
+ version: 3.5.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: webmock
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -110,8 +110,7 @@ homepage: http://github.com/amro/gibbon
110
110
  licenses:
111
111
  - MIT
112
112
  metadata: {}
113
- post_install_message: 'IMPORTANT: Gibbon now targets MailChimp API 3.0, which is very
114
- different from API 2.0. Use Gibbon 1.x if you need to target API 2.0.'
113
+ post_install_message:
115
114
  rdoc_options: []
116
115
  require_paths:
117
116
  - lib