mailchimp3 1.0.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.
- checksums.yaml +7 -0
- data/README.md +273 -0
- data/lib/mailchimp3.rb +19 -0
- data/lib/mailchimp3/endpoint.rb +114 -0
- data/lib/mailchimp3/errors.rb +39 -0
- data/lib/mailchimp3/oauth.rb +42 -0
- data/lib/mailchimp3/version.rb +3 -0
- data/spec/mailchimp3/endpoint_spec.rb +194 -0
- data/spec/mailchimp3/oauth_spec.rb +76 -0
- data/spec/mailchimp3_spec.rb +18 -0
- data/spec/spec_helper.rb +19 -0
- metadata +158 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2ed47a5c9aa596d1bd8ab0960067fecd28276112
|
4
|
+
data.tar.gz: c4106451d50a559f56e15b552d76e26cfbabfb93
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c58c68f2c6b1fcff8db1f90bf260ecf565ed74384053635353470f9512a6eb1591d186a35b186e72cb968ae98c2b6ff535a1e7de37aa29ba6a88d5e9d7974f81
|
7
|
+
data.tar.gz: 1a4a7c917560dba01b9e71a39f5570dc432af9a0589c0641c4ada87dc726d4fc23e233b802f24d663617df721ac12902856b3ff144653907652ea2f9bd651e39
|
data/README.md
ADDED
@@ -0,0 +1,273 @@
|
|
1
|
+
# MailChimp3
|
2
|
+
|
3
|
+
[](https://circleci.com/gh/seven1m/mailchimp3/tree/master)
|
4
|
+
|
5
|
+
`mailchimp3` is a Rubygem that provides a very thin, simple wrapper around the MailChimp RESTful JSON API version 3.0
|
6
|
+
documented at [kb.mailchimp.com/api](http://kb.mailchimp.com/api/).
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
```
|
11
|
+
gem install mailchimp3 (eventually)
|
12
|
+
```
|
13
|
+
|
14
|
+
## Usage with HTTP Basic Auth
|
15
|
+
|
16
|
+
1. Set your HTTP Basic auth key somewhere in your app
|
17
|
+
(probably an initializer if using Rails):
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
MailChimp3.config.basic_auth_key = 'key-us2'
|
21
|
+
```
|
22
|
+
|
23
|
+
2. Create a new API object and use it:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
# HTTP Basic
|
27
|
+
api = MailChimp3.new
|
28
|
+
```
|
29
|
+
|
30
|
+
3. Call a method on the api object to build the endpoint path.
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
api.lists
|
34
|
+
# /lists
|
35
|
+
```
|
36
|
+
|
37
|
+
4. For IDs, treat the object like a hash (use square brackets).
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
api.lists['abc123'].members
|
41
|
+
# /lists/abc123/members
|
42
|
+
```
|
43
|
+
|
44
|
+
5. To execute the request, use `get`, `post`, `patch`, or `delete`, optionally passing arguments.
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
api.lists.get(count: 25)
|
48
|
+
# GET /lists?count=25
|
49
|
+
api.lists['abc123'].members['cde345'].get
|
50
|
+
# GET /lists/abc123/members/cde345
|
51
|
+
```
|
52
|
+
|
53
|
+
### Usage with OAuth 2
|
54
|
+
|
55
|
+
1. Set your OAuth client id and secret somewhere in your app
|
56
|
+
(probably an initializer if using Rails):
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
MailChimp3.config.client_id = 'abc123'
|
60
|
+
MailChimp3.config.client_secret = 'xyz456'
|
61
|
+
```
|
62
|
+
|
63
|
+
2. (First time for each user) Get an OAuth 2 token by calling `MailChimp3.oauth.authorize_url` and redirect your user to it:
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
url = MailChimp3.oauth.authorize_url(
|
67
|
+
redirect_uri: 'http://example.com/oauth/callback'
|
68
|
+
)
|
69
|
+
redirect_to url
|
70
|
+
```
|
71
|
+
|
72
|
+
3. Upon redirect back to your app (in your `/oauth/callback` action),
|
73
|
+
call `MailChimp3.oauth.complete_auth`, passing in the `code` param
|
74
|
+
and the `redirect_uri` again.
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
data = MailChimp3.oauth.complete_auth(
|
78
|
+
params[:code],
|
79
|
+
redirect_uri: 'http://example.com/oauth/callback'
|
80
|
+
)
|
81
|
+
```
|
82
|
+
|
83
|
+
The hash returned looks like this:
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
{
|
87
|
+
token: <OAuth2::AccessToken>
|
88
|
+
token_string: 'abc123',
|
89
|
+
metadata: {
|
90
|
+
dc: 'us2'
|
91
|
+
}
|
92
|
+
}
|
93
|
+
```
|
94
|
+
|
95
|
+
Then get the authentication token and data center, and store it on
|
96
|
+
your user record for later use:
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
user.update_attributes(
|
100
|
+
mailchimp_auth_token: data[:token_string],
|
101
|
+
mailchimp_data_center: data[:metadata][:dc]
|
102
|
+
)
|
103
|
+
```
|
104
|
+
|
105
|
+
4. (Subsequent times for user) Instantiate the api object, passing in the
|
106
|
+
auth token and data center:
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
api = MailChimp3.new(
|
110
|
+
oauth_auth_token: user.mailchimp_auth_token,
|
111
|
+
dc: user.mailchimp_data_center
|
112
|
+
)
|
113
|
+
```
|
114
|
+
|
115
|
+
5. Use the `api` instance to make API calls!
|
116
|
+
|
117
|
+
## Example
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
require 'mailchimp3'
|
121
|
+
|
122
|
+
api = MailChimp3.new(basic_auth_key: 'abc123abc123abc123abc123abc123ab-us2')
|
123
|
+
api.lists.post(
|
124
|
+
name: 'Church.IO',
|
125
|
+
email_type_option: false,
|
126
|
+
permission_reminder: 'signed up on https://church.io'
|
127
|
+
contact: {
|
128
|
+
company: 'TJRM',
|
129
|
+
address1: '123 N. Main',
|
130
|
+
city: 'Tulsa',
|
131
|
+
state: 'OK',
|
132
|
+
zip: '74137',
|
133
|
+
country: 'US'
|
134
|
+
},
|
135
|
+
campaign_defaults: {
|
136
|
+
from_name: 'Tim Morgan',
|
137
|
+
from_email: 'tim@timmorgan.org',
|
138
|
+
subject: 'Hello World',
|
139
|
+
language: 'English'
|
140
|
+
},
|
141
|
+
)
|
142
|
+
```
|
143
|
+
|
144
|
+
...which returns something like:
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
{
|
148
|
+
"id" => "abc123abc1",
|
149
|
+
"name" => "Church.IO",
|
150
|
+
"contact" => {
|
151
|
+
"company" => "TJRM",
|
152
|
+
"address1" => "123 N. Main",
|
153
|
+
"address2" => "",
|
154
|
+
"city" => "Tulsa",
|
155
|
+
"state" => "OK",
|
156
|
+
"zip" => "74137",
|
157
|
+
"country" => "US",
|
158
|
+
"phone" => ""
|
159
|
+
},
|
160
|
+
"campaign_defaults" => {
|
161
|
+
"from_name" => "Tim Morgan",
|
162
|
+
"from_email" => "tim@timmorgan.org",
|
163
|
+
"subject" => "test",
|
164
|
+
"language" => "English"
|
165
|
+
},
|
166
|
+
# ...
|
167
|
+
"stats" => {
|
168
|
+
"member_count" => 0,
|
169
|
+
# ...
|
170
|
+
},
|
171
|
+
"_links" => [
|
172
|
+
{
|
173
|
+
"rel" => "self",
|
174
|
+
"href" => "https://us2.api.mailchimp.com/3.0/lists/abc123abc1",
|
175
|
+
"method" => "GET",
|
176
|
+
"targetSchema" => "https://us2.api.mailchimp.com/schema/3.0/Lists/Instance.json"
|
177
|
+
},
|
178
|
+
# ...
|
179
|
+
]
|
180
|
+
}
|
181
|
+
```
|
182
|
+
|
183
|
+
## get()
|
184
|
+
|
185
|
+
`get()` works for a collection (index) and a single resource (show).
|
186
|
+
|
187
|
+
```ruby
|
188
|
+
# collection
|
189
|
+
api.lists['abc123'].members.get(count: 25)
|
190
|
+
# => { members: array_of_resources }
|
191
|
+
|
192
|
+
# single resource
|
193
|
+
api.lists['abc123'].members['cde345'].get
|
194
|
+
# => resource_hash
|
195
|
+
```
|
196
|
+
|
197
|
+
## post()
|
198
|
+
|
199
|
+
`post()` sends a POST request to create a new resource.
|
200
|
+
|
201
|
+
```ruby
|
202
|
+
api.lists['abc123'].members.post(...)
|
203
|
+
# => resource_hash
|
204
|
+
```
|
205
|
+
|
206
|
+
## patch()
|
207
|
+
|
208
|
+
`patch()` sends a PATCH request to update an existing resource.
|
209
|
+
|
210
|
+
```ruby
|
211
|
+
api.lists['abc123'].members['cde345'].patch(...)
|
212
|
+
# => resource_hash
|
213
|
+
```
|
214
|
+
|
215
|
+
## delete()
|
216
|
+
|
217
|
+
`delete()` sends a DELETE request to delete an existing resource. This method returns `true` if the delete was successful.
|
218
|
+
|
219
|
+
```ruby
|
220
|
+
api.lists['abc123'].members['cde345'].delete
|
221
|
+
# => true
|
222
|
+
```
|
223
|
+
|
224
|
+
## Errors
|
225
|
+
|
226
|
+
The following errors may be raised by the library, depending on the API response status code.
|
227
|
+
|
228
|
+
| HTTP Status Codes | Error Class |
|
229
|
+
| ------------------- | ----------------------------------------------------------------------------- |
|
230
|
+
| 400 | `MailChimp3::Errors::BadRequest` < `MailChimp3::Errors::ClientError` |
|
231
|
+
| 401 | `MailChimp3::Errors::Unauthorized` < `MailChimp3::Errors::ClientError` |
|
232
|
+
| 403 | `MailChimp3::Errors::Forbidden` < `MailChimp3::Errors::ClientError` |
|
233
|
+
| 404 | `MailChimp3::Errors::NotFound` < `MailChimp3::Errors::ClientError` |
|
234
|
+
| 405 | `MailChimp3::Errors::MethodNotAllowed` < `MailChimp3::Errors::ClientError` |
|
235
|
+
| 422 | `MailChimp3::Errors::UnprocessableEntity` < `MailChimp3::Errors::ClientError` |
|
236
|
+
| other 4xx errors | `MailChimp3::Errors::ClientError` |
|
237
|
+
| 500 | `MailChimp3::Errors::InternalServerError` < `MailChimp3::Errors::ServerError` |
|
238
|
+
| other 5xx errors | `MailChimp3::Errors::ServerError` |
|
239
|
+
|
240
|
+
The exception object has the following methods:
|
241
|
+
|
242
|
+
| Method | Content |
|
243
|
+
| ------- | ---------------------------------------- |
|
244
|
+
| status | HTTP status code returned by the server |
|
245
|
+
| message | the message returned by the API |
|
246
|
+
| details | the full response returned by the server |
|
247
|
+
|
248
|
+
The `message` should be a simple string given by the API, e.g. "Resource Not Found".
|
249
|
+
|
250
|
+
`details` is a Ruby hash containing all the details given by the server, and looks like this:
|
251
|
+
|
252
|
+
```ruby
|
253
|
+
{
|
254
|
+
"type" => "http://kb.mailchimp.com/api/error-docs/400-invalid-resource",
|
255
|
+
"title" => "Invalid Resource",
|
256
|
+
"status" => 400,
|
257
|
+
"detail" => "The resource submitted could not be validated. For field-specific details, see the 'errors' array.",
|
258
|
+
"instance" => "286179fe-f3dc-4c03-8c14-1021cf0191a2",
|
259
|
+
"errors" => [
|
260
|
+
{
|
261
|
+
"field" => "",
|
262
|
+
"message" => "Required fields were not provided: permission_reminder, campaign_defaults"
|
263
|
+
}
|
264
|
+
]
|
265
|
+
}
|
266
|
+
```
|
267
|
+
|
268
|
+
Alternatively, you may rescue `MailChimp3::Errors::BaseError` and branch your code based on
|
269
|
+
the status code returned by calling `error.status`.
|
270
|
+
|
271
|
+
## Copyright & License
|
272
|
+
|
273
|
+
Copyright 2015, Tim Morgan. Licensed MIT.
|
data/lib/mailchimp3.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative 'mailchimp3/endpoint'
|
2
|
+
require_relative 'mailchimp3/oauth'
|
3
|
+
require_relative 'mailchimp3/errors'
|
4
|
+
|
5
|
+
module MailChimp3
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def new(*args)
|
9
|
+
Endpoint.new(*args)
|
10
|
+
end
|
11
|
+
|
12
|
+
def config
|
13
|
+
@config ||= Struct.new(:client_id, :client_secret).new
|
14
|
+
end
|
15
|
+
|
16
|
+
def oauth
|
17
|
+
@oauth ||= MailChimp3::OAuth.new
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'faraday_middleware'
|
3
|
+
|
4
|
+
module MailChimp3
|
5
|
+
class Endpoint
|
6
|
+
attr_reader :url, :last_result
|
7
|
+
|
8
|
+
def initialize(oauth_access_token: nil, basic_auth_key: nil, dc: nil, url: nil)
|
9
|
+
@oauth_access_token = oauth_access_token
|
10
|
+
@basic_auth_key = basic_auth_key
|
11
|
+
@dc = dc
|
12
|
+
@dc ||= @basic_auth_key.split('-').last if @basic_auth_key
|
13
|
+
@url = url || _build_url
|
14
|
+
fail Errors::DataCenterRequiredError, 'You must pass dc.' unless @dc || @url
|
15
|
+
@cache = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def method_missing(method_name, *_args)
|
19
|
+
_build_endpoint(method_name.to_s)
|
20
|
+
end
|
21
|
+
|
22
|
+
def [](id)
|
23
|
+
_build_endpoint(id.to_s)
|
24
|
+
end
|
25
|
+
|
26
|
+
def get(params = {})
|
27
|
+
@last_result = _connection.get(@url, params)
|
28
|
+
_build_response(@last_result)
|
29
|
+
end
|
30
|
+
|
31
|
+
def post(body = {})
|
32
|
+
@last_result = _connection.post(@url) do |req|
|
33
|
+
req.body = body.to_json
|
34
|
+
end
|
35
|
+
_build_response(@last_result)
|
36
|
+
end
|
37
|
+
|
38
|
+
def patch(body = {})
|
39
|
+
@last_result = _connection.patch(@url) do |req|
|
40
|
+
req.body = body.to_json
|
41
|
+
end
|
42
|
+
_build_response(@last_result)
|
43
|
+
end
|
44
|
+
|
45
|
+
def delete
|
46
|
+
@last_result = _connection.delete(@url)
|
47
|
+
if @last_result.status == 204
|
48
|
+
true
|
49
|
+
else
|
50
|
+
_build_response(@last_result)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def _build_response(result)
|
57
|
+
case result.status
|
58
|
+
when 200..299
|
59
|
+
result.body
|
60
|
+
when 400
|
61
|
+
fail Errors::BadRequest, result
|
62
|
+
when 401
|
63
|
+
fail Errors::Unauthorized, result
|
64
|
+
when 403
|
65
|
+
fail Errors::Forbidden, result
|
66
|
+
when 404
|
67
|
+
fail Errors::NotFound, result
|
68
|
+
when 405
|
69
|
+
fail Errors::MethodNotAllowed, result
|
70
|
+
when 422
|
71
|
+
fail Errors::UnprocessableEntity, result
|
72
|
+
when 400..499
|
73
|
+
fail Errors::ClientError, result
|
74
|
+
when 500
|
75
|
+
fail Errors::InternalServerError, result
|
76
|
+
when 500..599
|
77
|
+
fail Errors::ServerError, result
|
78
|
+
else
|
79
|
+
binding.pry
|
80
|
+
fail "unknown status #{result.status}"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def _build_endpoint(path)
|
85
|
+
@cache[path] ||= begin
|
86
|
+
self.class.new(
|
87
|
+
url: File.join(url, path.to_s),
|
88
|
+
basic_auth_key: @basic_auth_key,
|
89
|
+
oauth_access_token: @oauth_access_token
|
90
|
+
)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def _build_url
|
95
|
+
url = "https://#{@dc}.api.mailchimp.com/3.0"
|
96
|
+
url << '/' if url =~ /3\.0\z/ # workaround for the api requiring a slash on the root urls
|
97
|
+
url
|
98
|
+
end
|
99
|
+
|
100
|
+
def _connection
|
101
|
+
@connection ||= Faraday.new(url: url) do |faraday|
|
102
|
+
faraday.adapter :excon
|
103
|
+
faraday.response :json, content_type: /\bjson$/
|
104
|
+
if @basic_auth_key
|
105
|
+
faraday.basic_auth '', @basic_auth_key
|
106
|
+
elsif @oauth_access_token
|
107
|
+
faraday.headers['Authorization'] = "Bearer #{@oauth_access_token}"
|
108
|
+
else
|
109
|
+
fail Errors::AuthRequiredError, "You must specify either HTTP basic auth credentials or an OAuth2 access token."
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module MailChimp3
|
2
|
+
module Errors
|
3
|
+
class AuthRequiredError < StandardError; end
|
4
|
+
class DataCenterRequiredError < StandardError; end
|
5
|
+
|
6
|
+
class BaseError < StandardError
|
7
|
+
attr_reader :status, :details
|
8
|
+
|
9
|
+
def initialize(response)
|
10
|
+
@status = response.status
|
11
|
+
@message = if response.body.is_a?(Hash)
|
12
|
+
"#{response.body['title']}: #{response.body['detail']}"
|
13
|
+
else
|
14
|
+
response.body.to_s
|
15
|
+
end
|
16
|
+
@details = response.body if response.body.is_a?(Hash)
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
@message
|
21
|
+
end
|
22
|
+
|
23
|
+
def inspect
|
24
|
+
"<#{self.class.name} status=#{@status} message=#{@message}>"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class ClientError < BaseError; end # 400..499
|
29
|
+
class BadRequest < ClientError; end # 400
|
30
|
+
class Unauthorized < ClientError; end # 401
|
31
|
+
class Forbidden < ClientError; end # 403
|
32
|
+
class NotFound < ClientError; end # 404
|
33
|
+
class MethodNotAllowed < ClientError; end # 405
|
34
|
+
class UnprocessableEntity < ClientError; end # 422
|
35
|
+
|
36
|
+
class ServerError < BaseError; end # 500..599
|
37
|
+
class InternalServerError < ServerError; end # 500
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'oauth2'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module MailChimp3
|
5
|
+
class OAuth
|
6
|
+
def initialize
|
7
|
+
@oauth = OAuth2::Client.new(
|
8
|
+
MailChimp3.config.client_id,
|
9
|
+
MailChimp3.config.client_secret,
|
10
|
+
site: 'https://login.mailchimp.com',
|
11
|
+
authorize_url: '/oauth2/authorize',
|
12
|
+
token_url: '/oauth2/token'
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
def authorize_url(redirect_uri:)
|
17
|
+
@oauth.auth_code.authorize_url(redirect_uri: redirect_uri)
|
18
|
+
end
|
19
|
+
|
20
|
+
def complete_auth(code, redirect_uri:)
|
21
|
+
token = @oauth.auth_code.get_token(
|
22
|
+
code,
|
23
|
+
redirect_uri: redirect_uri
|
24
|
+
)
|
25
|
+
{
|
26
|
+
token: token,
|
27
|
+
token_string: token.token,
|
28
|
+
metadata: metadata(token)
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def metadata(token)
|
35
|
+
JSON.parse(token.get('/oauth2/metadata').body).tap do |hash|
|
36
|
+
hash.keys.each do |key|
|
37
|
+
hash[key.to_sym] = hash.delete(key)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,194 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
describe MailChimp3::Endpoint do
|
5
|
+
let(:base) { described_class.new(basic_auth_key: 'key-us2') }
|
6
|
+
|
7
|
+
subject { base }
|
8
|
+
|
9
|
+
describe '#method_missing' do
|
10
|
+
before do
|
11
|
+
@result = subject.lists
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'returns a wrapper object with updated url' do
|
15
|
+
expect(@result).to be_a(described_class)
|
16
|
+
expect(@result.url).to match(%r{/lists$})
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#[]' do
|
21
|
+
before do
|
22
|
+
@result = subject.lists[1]
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'returns a wrapper object with updated url' do
|
26
|
+
expect(@result).to be_a(described_class)
|
27
|
+
expect(@result.url).to match(%r{/lists/1$})
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#get' do
|
32
|
+
context 'given a good URL' do
|
33
|
+
subject { base.lists }
|
34
|
+
|
35
|
+
let(:result) do
|
36
|
+
{
|
37
|
+
'id' => 'e8bcf09f6f',
|
38
|
+
'name' => 'My List'
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
before do
|
43
|
+
stub_request(:get, 'https://us2.api.mailchimp.com/3.0/lists')
|
44
|
+
.to_return(status: 200, body: { lists: result }.to_json, headers: { 'Content-Type' => 'application/json; charset=utf-8' })
|
45
|
+
@result = subject.get
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'returns the result of making a GET request to the endpoint' do
|
49
|
+
expect(@result).to be_a(Hash)
|
50
|
+
expect(@result['lists']).to eq(result)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'given a non-existent URL' do
|
55
|
+
subject { base.non_existent }
|
56
|
+
|
57
|
+
let(:result) do
|
58
|
+
{
|
59
|
+
'status' => 404,
|
60
|
+
'title' => 'Resource Not Found',
|
61
|
+
'detail' => 'The requested resource could not be found.'
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
before do
|
66
|
+
stub_request(:get, 'https://us2.api.mailchimp.com/3.0/non_existent')
|
67
|
+
.to_return(status: 404, body: result.to_json, headers: { 'Content-Type' => 'application/json; charset=utf-8' })
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'raises a NotFound error' do
|
71
|
+
error = begin
|
72
|
+
subject.get
|
73
|
+
rescue MailChimp3::Errors::NotFound => e
|
74
|
+
e
|
75
|
+
end
|
76
|
+
expect(error.status).to eq(404)
|
77
|
+
expect(error.message).to eq('Resource Not Found: The requested resource could not be found.')
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'given a client error' do
|
82
|
+
subject { base.error }
|
83
|
+
|
84
|
+
let(:result) do
|
85
|
+
{
|
86
|
+
'status' => 400,
|
87
|
+
'title' => 'Bad request'
|
88
|
+
}
|
89
|
+
end
|
90
|
+
|
91
|
+
before do
|
92
|
+
stub_request(:get, 'https://us2.api.mailchimp.com/3.0/error')
|
93
|
+
.to_return(status: 400, body: result.to_json, headers: { 'Content-Type' => 'application/json; charset=utf-8' })
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'raises a ClientError error' do
|
97
|
+
expect {
|
98
|
+
subject.get
|
99
|
+
}.to raise_error(MailChimp3::Errors::ClientError)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context 'given a server error' do
|
104
|
+
subject { base.error }
|
105
|
+
|
106
|
+
let(:result) do
|
107
|
+
{
|
108
|
+
'status' => 500,
|
109
|
+
'title' => 'System error has occurred'
|
110
|
+
}
|
111
|
+
end
|
112
|
+
|
113
|
+
before do
|
114
|
+
stub_request(:get, 'https://us2.api.mailchimp.com/3.0/error')
|
115
|
+
.to_return(status: 500, body: result.to_json, headers: { 'Content-Type' => 'application/json; charset=utf-8' })
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'raises a ServerError error' do
|
119
|
+
expect {
|
120
|
+
subject.get
|
121
|
+
}.to raise_error(MailChimp3::Errors::ServerError)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe '#post' do
|
127
|
+
subject { base.lists }
|
128
|
+
|
129
|
+
let(:resource) do
|
130
|
+
{
|
131
|
+
'name' => 'Foo'
|
132
|
+
}
|
133
|
+
end
|
134
|
+
|
135
|
+
let(:result) do
|
136
|
+
{
|
137
|
+
'id' => 'd3ed40bd7c',
|
138
|
+
'name' => 'Foo'
|
139
|
+
}
|
140
|
+
end
|
141
|
+
|
142
|
+
before do
|
143
|
+
stub_request(:post, 'https://us2.api.mailchimp.com/3.0/lists')
|
144
|
+
.to_return(status: 201, body: result.to_json, headers: { 'Content-Type' => 'application/json; charset=utf-8' })
|
145
|
+
@result = subject.post(resource)
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'returns the result of making a POST request to the endpoint' do
|
149
|
+
expect(@result).to eq(result)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe '#patch' do
|
154
|
+
subject { base.lists['d3ed40bd7c'] }
|
155
|
+
|
156
|
+
let(:resource) do
|
157
|
+
{
|
158
|
+
'id' => 'd3ed40bd7c',
|
159
|
+
'name' => 'Foo'
|
160
|
+
}
|
161
|
+
end
|
162
|
+
|
163
|
+
let(:result) do
|
164
|
+
{
|
165
|
+
'id' => 'd3ed40bd7c',
|
166
|
+
'name' => 'Foo'
|
167
|
+
}
|
168
|
+
end
|
169
|
+
|
170
|
+
before do
|
171
|
+
stub_request(:patch, 'https://us2.api.mailchimp.com/3.0/lists/d3ed40bd7c')
|
172
|
+
.to_return(status: 200, body: result.to_json, headers: { 'Content-Type' => 'application/json; charset=utf-8' })
|
173
|
+
@result = subject.patch(resource)
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'returns the result of making a PATCH request to the endpoint' do
|
177
|
+
expect(@result).to eq(result)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe '#delete' do
|
182
|
+
subject { base.lists['d3ed40bd7c'] }
|
183
|
+
|
184
|
+
before do
|
185
|
+
stub_request(:delete, 'https://us2.api.mailchimp.com/3.0/lists/d3ed40bd7c')
|
186
|
+
.to_return(status: 204, body: '')
|
187
|
+
@result = subject.delete
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'returns true' do
|
191
|
+
expect(@result).to eq(true)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
MailChimp3.config.client_id = 'foo'
|
4
|
+
MailChimp3.config.client_secret = 'bar'
|
5
|
+
|
6
|
+
describe MailChimp3::OAuth do
|
7
|
+
subject { MailChimp3.oauth }
|
8
|
+
|
9
|
+
describe '#authorize_url' do
|
10
|
+
it 'returns the authorization url' do
|
11
|
+
url = subject.authorize_url(
|
12
|
+
redirect_uri: 'http://example.com/oauth/callback'
|
13
|
+
)
|
14
|
+
expect(url).to eq('https://login.mailchimp.com/oauth2/authorize?client_id=foo&redirect_uri=http%3A%2F%2Fexample.com%2Foauth%2Fcallback&response_type=code')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#complete_auth' do
|
19
|
+
before do
|
20
|
+
stub_request(:post, 'https://login.mailchimp.com/oauth2/token')
|
21
|
+
.with(body: {
|
22
|
+
'client_id' => 'foo',
|
23
|
+
'client_secret' => 'bar',
|
24
|
+
'code' => '1234567890',
|
25
|
+
'grant_type' => 'authorization_code',
|
26
|
+
'redirect_uri' => 'http://example.com/oauth/callback'
|
27
|
+
})
|
28
|
+
.to_return(
|
29
|
+
status: 200,
|
30
|
+
body: {
|
31
|
+
access_token: '925680f04933b28f128d721fdf8949fa',
|
32
|
+
expires_in: 0,
|
33
|
+
scope: nil
|
34
|
+
}.to_json,
|
35
|
+
headers: {
|
36
|
+
'Content-Type' => 'application/json'
|
37
|
+
}
|
38
|
+
)
|
39
|
+
stub_request(:get, 'https://login.mailchimp.com/oauth2/metadata')
|
40
|
+
.with(headers: {
|
41
|
+
'Authorization' => 'Bearer 925680f04933b28f128d721fdf8949fa'
|
42
|
+
})
|
43
|
+
.to_return(
|
44
|
+
status: 200,
|
45
|
+
body: {
|
46
|
+
dc: 'us2',
|
47
|
+
role: 'owner',
|
48
|
+
accountname: 'timmorgan',
|
49
|
+
user_id: 2472146,
|
50
|
+
login: {
|
51
|
+
email: 'tim@timmorgan.org',
|
52
|
+
avatar: nil,
|
53
|
+
login_id: 2472146,
|
54
|
+
login_name: 'timmorgan',
|
55
|
+
login_email:'tim@timmorgan.org'
|
56
|
+
},
|
57
|
+
login_url: 'https://login.mailchimp.com',
|
58
|
+
api_endpoint: 'https://us2.api.mailchimp.com'
|
59
|
+
}.to_json)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'stores the auth token and metadata' do
|
63
|
+
url = subject.authorize_url(
|
64
|
+
redirect_uri: 'http://example.com/oauth/callback'
|
65
|
+
)
|
66
|
+
hash = subject.complete_auth(
|
67
|
+
'1234567890',
|
68
|
+
redirect_uri: 'http://example.com/oauth/callback'
|
69
|
+
)
|
70
|
+
expect(hash[:token]).to be_an(OAuth2::AccessToken)
|
71
|
+
expect(hash[:token_string]).to eq('925680f04933b28f128d721fdf8949fa')
|
72
|
+
expect(hash[:metadata]).to be_a(Hash)
|
73
|
+
expect(hash[:metadata][:dc]).to eq('us2')
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe MailChimp3 do
|
4
|
+
describe '#config' do
|
5
|
+
it 'returns configuration object' do
|
6
|
+
subject.config.client_id = 'foo'
|
7
|
+
subject.config.client_secret = 'bar'
|
8
|
+
expect(subject.config.client_id).to eq('foo')
|
9
|
+
expect(subject.config.client_secret).to eq('bar')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#oauth' do
|
14
|
+
it 'returns a MailChimp3::OAuth instance' do
|
15
|
+
expect(subject.oauth).to be_a(MailChimp3::OAuth)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'webmock/rspec'
|
2
|
+
require 'pry'
|
3
|
+
|
4
|
+
require_relative '../lib/mailchimp3'
|
5
|
+
|
6
|
+
RSpec.configure do |config|
|
7
|
+
config.expect_with :rspec do |expectations|
|
8
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
9
|
+
end
|
10
|
+
|
11
|
+
config.mock_with :rspec do |mocks|
|
12
|
+
mocks.verify_partial_doubles = true
|
13
|
+
end
|
14
|
+
|
15
|
+
config.color = true
|
16
|
+
config.order = 'random'
|
17
|
+
config.filter_run focus: true
|
18
|
+
config.run_all_when_everything_filtered = true
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mailchimp3
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tim Morgan
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-06-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: faraday
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.9.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.9.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: faraday_middleware
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.9.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.9.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: excon
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.45.3
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.45.3
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: oauth2
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.0.0
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.0.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.2'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.2'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: webmock
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.21'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.21'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pry
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.10'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.10'
|
111
|
+
description: mailchimp3 is a gem for working with MailChimp's RESTful JSON API documented
|
112
|
+
at http://kb.mailchimp.com/api/ using HTTP basic auth or OAuth 2.0. This library
|
113
|
+
can talk to any endpoint the API provides, since it is written to build endpoint
|
114
|
+
URLs dynamically using method_missing.
|
115
|
+
email: tim@timmorgan.org
|
116
|
+
executables: []
|
117
|
+
extensions: []
|
118
|
+
extra_rdoc_files: []
|
119
|
+
files:
|
120
|
+
- README.md
|
121
|
+
- lib/mailchimp3.rb
|
122
|
+
- lib/mailchimp3/endpoint.rb
|
123
|
+
- lib/mailchimp3/errors.rb
|
124
|
+
- lib/mailchimp3/oauth.rb
|
125
|
+
- lib/mailchimp3/version.rb
|
126
|
+
- spec/mailchimp3/endpoint_spec.rb
|
127
|
+
- spec/mailchimp3/oauth_spec.rb
|
128
|
+
- spec/mailchimp3_spec.rb
|
129
|
+
- spec/spec_helper.rb
|
130
|
+
homepage: https://github.com/seven1m/mailchimp3
|
131
|
+
licenses:
|
132
|
+
- MIT
|
133
|
+
metadata: {}
|
134
|
+
post_install_message:
|
135
|
+
rdoc_options: []
|
136
|
+
require_paths:
|
137
|
+
- lib
|
138
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: 2.0.0
|
143
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - ">="
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0'
|
148
|
+
requirements: []
|
149
|
+
rubyforge_project:
|
150
|
+
rubygems_version: 2.4.6
|
151
|
+
signing_key:
|
152
|
+
specification_version: 4
|
153
|
+
summary: wrapper for MailChimp's 3.0 API
|
154
|
+
test_files:
|
155
|
+
- spec/mailchimp3/endpoint_spec.rb
|
156
|
+
- spec/mailchimp3/oauth_spec.rb
|
157
|
+
- spec/mailchimp3_spec.rb
|
158
|
+
- spec/spec_helper.rb
|