gibbon 1.2.1 → 2.0.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.

@@ -1,5 +1,5 @@
1
1
  module Gibbon
2
2
  class MailChimpError < StandardError
3
- attr_accessor :code, :name
3
+ attr_accessor :title, :detail, :body, :raw_body, :status_code
4
4
  end
5
5
  end
@@ -0,0 +1,65 @@
1
+ module Gibbon
2
+ class Request
3
+ attr_accessor :api_key, :api_endpoint, :timeout
4
+
5
+ DEFAULT_TIMEOUT = 30
6
+
7
+ def initialize(api_key: nil, api_endpoint: nil, timeout: nil)
8
+ @path_parts = []
9
+ @api_key = api_key || self.class.api_key || ENV['MAILCHIMP_API_KEY']
10
+ @api_key = @api_key.strip if @api_key
11
+ @api_endpoint = api_endpoint || self.class.api_endpoint
12
+ @timeout = timeout || self.class.timeout || DEFAULT_TIMEOUT
13
+ end
14
+
15
+ def method_missing(method, *args)
16
+ # To support underscores, we replace them with hyphens when calling the API
17
+ @path_parts << method.to_s.gsub("_", "-").downcase
18
+ @path_parts << args if args.length > 0
19
+ @path_parts.flatten!
20
+ self
21
+ end
22
+
23
+ def path
24
+ @path_parts.join('/')
25
+ end
26
+
27
+ def create(params: nil, headers: nil, body: nil)
28
+ APIRequest.new(builder: self).post(params: params, headers: headers, body: body)
29
+ ensure
30
+ reset
31
+ end
32
+
33
+ def update(params: nil, headers: nil, body: nil)
34
+ APIRequest.new(builder: self).patch(params: params, headers: headers, body: body)
35
+ ensure
36
+ reset
37
+ end
38
+
39
+ def retrieve(params: nil, headers: nil)
40
+ APIRequest.new(builder: self).get(params: params, headers: headers)
41
+ ensure
42
+ reset
43
+ end
44
+
45
+ def delete(params: nil, headers: nil)
46
+ APIRequest.new(builder: self).delete(params: params, headers: headers)
47
+ ensure
48
+ reset
49
+ end
50
+
51
+ protected
52
+
53
+ def reset
54
+ @path_parts = []
55
+ end
56
+
57
+ class << self
58
+ attr_accessor :api_key, :timeout, :api_endpoint
59
+
60
+ def method_missing(sym, *args, &block)
61
+ new(api_key: self.api_key, api_endpoint: self.api_endpoint, timeout: self.timeout).send(sym, *args, &block)
62
+ end
63
+ end
64
+ end
65
+ end
@@ -1,3 +1,3 @@
1
1
  module Gibbon
2
- VERSION = "1.2.1"
3
- end
2
+ VERSION = "2.0.0"
3
+ end
@@ -1,87 +1,83 @@
1
1
  require 'spec_helper'
2
2
  require 'cgi'
3
- require 'webmock'
4
- require 'webmock/rspec'
5
3
 
6
4
  describe Gibbon do
7
-
8
5
  describe "attributes" do
9
-
10
6
  before do
7
+ Gibbon::APIRequest.send(:public, *Gibbon::APIRequest.protected_instance_methods)
8
+
11
9
  @api_key = "123-us1"
12
10
  end
13
11
 
14
12
  it "have no API by default" do
15
- @gibbon = Gibbon::API.new
13
+ @gibbon = Gibbon::Request.new
16
14
  expect(@gibbon.api_key).to be_nil
17
15
  end
18
16
 
19
17
  it "set an API key in constructor" do
20
- @gibbon = Gibbon::API.new(@api_key)
18
+ @gibbon = Gibbon::Request.new(api_key: @api_key)
21
19
  expect(@gibbon.api_key).to eq(@api_key)
22
20
  end
23
21
 
24
22
  it "set an API key from the 'MAILCHIMP_API_KEY' ENV variable" do
25
23
  ENV['MAILCHIMP_API_KEY'] = @api_key
26
- @gibbon = Gibbon::API.new
24
+ @gibbon = Gibbon::Request.new
27
25
  expect(@gibbon.api_key).to eq(@api_key)
28
26
  ENV.delete('MAILCHIMP_API_KEY')
29
27
  end
30
28
 
31
29
  it "set an API key via setter" do
32
- @gibbon = Gibbon::API.new
30
+ @gibbon = Gibbon::Request.new
33
31
  @gibbon.api_key = @api_key
34
32
  expect(@gibbon.api_key).to eq(@api_key)
35
33
  end
36
34
 
37
35
  it "set timeout and get" do
38
- @gibbon = Gibbon::API.new
36
+ @gibbon = Gibbon::Request.new
39
37
  timeout = 30
40
38
  @gibbon.timeout = timeout
41
39
  expect(timeout).to eq(@gibbon.timeout)
42
40
  end
43
41
 
42
+ it "timeout properly passed to APIRequest" do
43
+ @gibbon = Gibbon::Request.new
44
+ timeout = 30
45
+ @gibbon.timeout = timeout
46
+ @request = Gibbon::APIRequest.new(builder: @gibbon)
47
+ expect(timeout).to eq(@request.timeout)
48
+ end
49
+
44
50
  it "detect api endpoint from initializer parameters" do
45
51
  api_endpoint = 'https://us6.api.mailchimp.com'
46
- @gibbon = Gibbon::API.new(@api_key, :api_endpoint => api_endpoint)
52
+ @gibbon = Gibbon::Request.new(api_key: @api_key, api_endpoint: api_endpoint)
47
53
  expect(api_endpoint).to eq(@gibbon.api_endpoint)
48
54
  end
49
-
50
- it "sets the 'throws_exceptions' option from initializer parameters" do
51
- @gibbon = Gibbon::API.new(@api_key, :throws_exceptions => false)
52
- expect(false).to eq(@gibbon.throws_exceptions)
53
- end
54
55
  end
55
56
 
56
57
  describe "build api url" do
57
58
  before do
58
- @gibbon = Gibbon::API.new
59
- @url = "https://api.mailchimp.com/2.0/say/hello"
59
+ Gibbon::APIRequest.send(:public, *Gibbon::APIRequest.protected_instance_methods)
60
+
61
+ @gibbon = Gibbon::Request.new
62
+ @url = "https://api.mailchimp.com/3.0/lists/"
60
63
  end
61
64
 
62
65
  it "doesn't allow empty api key" do
63
- expect {@gibbon.say.hello}.to raise_error(Gibbon::GibbonError)
66
+ expect {@gibbon.try.retrieve}.to raise_error(Gibbon::GibbonError)
64
67
  end
65
68
 
66
- it "handle malformed api key" do
69
+ it "doesn't allow api key without data center" do
67
70
  @api_key = "123"
68
71
  @gibbon.api_key = @api_key
69
- expect_post(@url, {"apikey" => @api_key})
70
- @gibbon.say.hello
72
+ expect {@gibbon.try.retrieve}.to raise_error(Gibbon::GibbonError)
71
73
  end
72
74
 
73
- it "handle timeout" do
74
- expect_post(@url, {"apikey" => 'test'}, 120)
75
- @gibbon.api_key = 'test'
76
- @gibbon.timeout=120
77
- @gibbon.say.hello
78
- end
79
-
80
- it "handle api key with dc" do
75
+ it "sets correct endpoint from api key" do
81
76
  @api_key = "TESTKEY-us1"
82
77
  @gibbon.api_key = @api_key
83
- expect_post("https://us1.api.mailchimp.com/2.0/say/hello", {"apikey" => @api_key})
84
- @gibbon.say.hello
78
+ @gibbon.try
79
+ @request = Gibbon::APIRequest.new(builder: @gibbon)
80
+ expect(@request.api_url).to eq("https://us1.api.mailchimp.com/3.0/try")
85
81
  end
86
82
 
87
83
  # when the end user has signed in via oauth, api_key and endpoint it be supplied separately
@@ -89,232 +85,36 @@ describe Gibbon do
89
85
  @api_key = "TESTKEY"
90
86
  @gibbon.api_key = @api_key
91
87
  @gibbon.api_endpoint = "https://us6.api.mailchimp.com"
92
- expect_post("https://us6.api.mailchimp.com/2.0/say/hello", {"apikey" => @api_key})
93
- @gibbon.say.hello
88
+ @request = Gibbon::APIRequest.new(builder: @gibbon)
89
+ expect {@request.validate_api_key}.not_to raise_error
94
90
  end
95
91
  end
96
92
 
97
- describe "Gibbon class variables" do
93
+ describe "class variables" do
98
94
  before do
99
- Gibbon::API.api_key = "123-us1"
100
- Gibbon::API.timeout = 15
101
- Gibbon::API.throws_exceptions = false
102
- Gibbon::API.api_endpoint = 'https://us6.api.mailchimp.com'
95
+ Gibbon::Request.api_key = "123-us1"
96
+ Gibbon::Request.timeout = 15
97
+ Gibbon::Request.api_endpoint = 'https://us6.api.mailchimp.com'
103
98
  end
104
99
 
105
100
  after do
106
- Gibbon::API.api_key = nil
107
- Gibbon::API.timeout = nil
108
- Gibbon::API.throws_exceptions = nil
109
- Gibbon::API.api_endpoint = nil
101
+ Gibbon::Request.api_key = nil
102
+ Gibbon::Request.timeout = nil
103
+ Gibbon::Request.api_endpoint = nil
110
104
  end
111
105
 
112
106
  it "set api key on new instances" do
113
- expect(Gibbon::API.new.api_key).to eq(Gibbon::API.api_key)
107
+ expect(Gibbon::Request.new.api_key).to eq(Gibbon::Request.api_key)
114
108
  end
115
109
 
116
110
  it "set timeout on new instances" do
117
- expect(Gibbon::API.new.timeout).to eq(Gibbon::API.timeout)
118
- end
119
-
120
- it "set throws_exceptions on new instances" do
121
- expect(Gibbon::API.new.throws_exceptions).to eq(Gibbon::API.throws_exceptions)
111
+ expect(Gibbon::Request.new.timeout).to eq(Gibbon::Request.timeout)
122
112
  end
123
113
 
124
114
  it "set api_endpoint on new instances" do
125
- expect(Gibbon::API.api_endpoint).not_to be_nil
126
- expect(Gibbon::API.new.api_endpoint).to eq(Gibbon::API.api_endpoint)
127
- end
128
- end
129
-
130
- describe "build api body" do
131
- before do
132
- @key = "TESTKEY-us1"
133
- @gibbon = Gibbon::API.new(@key)
134
- @url = "https://us1.api.mailchimp.com/2.0/say/hello"
135
- @body = {"apikey" => @key}
136
- end
137
-
138
- it "works for string parameters" do
139
- @message = "simon says"
140
- expect_post(@url, @body.merge("message" => @message))
141
- @gibbon.say.hello(:message => @message)
142
- end
143
-
144
- it "works for string parameters in an array" do
145
- expect_post(@url, @body.merge("messages" => ["simon says", "do this"]))
146
- @gibbon.say.hello(:messages => ["simon says", "do this"])
147
- end
148
-
149
- it "works for string parameters in a hash" do
150
- expect_post(@url, @body.merge("messages" => {"simon says" => "do this"}))
151
- @gibbon.say.hello(:messages => {"simon says" => "do this"})
152
- end
153
-
154
- it "works for nested string parameters" do
155
- expect_post(@url, @body.merge("messages" => {"simon says" => ["do this", "and this"]}))
156
- @gibbon.say.hello(:messages => {"simon says" => ["do this", "and this"]})
157
- end
158
-
159
- it "pass through non string parameters" do
160
- expect_post(@url, @body.merge("fee" => 99))
161
- @gibbon.say.hello(:fee => 99)
162
- end
163
-
164
- it "pass through http header settings" do
165
- @gibbon.timeout=30
166
- expect_post(@url, @body.merge("messages" => 'Simon says'), @gibbon.timeout, {'Accept-Language' => 'en'})
167
- @gibbon.say.hello(:messages => 'Simon says', :headers => {'Accept-Language' => 'en'} )
168
- end
169
-
170
- it "with http headers not set" do
171
- @gibbon.timeout=30
172
- expect_post(@url, @body.merge("messages" => 'Simon says'), @gibbon.timeout, {})
173
- @gibbon.say.hello(:messages => 'Simon says' )
174
- end
175
-
176
- end
177
-
178
- describe "Gibbon instances" do
179
- before do
180
- @key = "TESTKEY-us1"
181
- @gibbon = Gibbon::API.new(@key)
182
- @url = "https://us1.api.mailchimp.com/2.0/say/hello"
183
- @body = {"apikey" => @key}
184
- @returns = Struct.new(:body).new(MultiJson.dump(["array", "entries"]))
185
- end
186
-
187
- it "produce a good exporter" do
188
- @exporter = @gibbon.get_exporter
189
- expect(@exporter.api_key).to eq(@gibbon.api_key)
190
- end
191
-
192
- it "not throw exception if configured to and the API replies with a JSON hash containing a key called 'error'" do
193
- @gibbon.throws_exceptions = false
194
- allow(Gibbon::APICategory).to receive(:post).and_return(Struct.new(:body).new(MultiJson.dump({'error' => 'bad things'})))
195
-
196
- @gibbon.say.hello
115
+ expect(Gibbon::Request.api_endpoint).not_to be_nil
116
+ expect(Gibbon::Request.new.api_endpoint).to eq(Gibbon::Request.api_endpoint)
197
117
  end
198
-
199
- it "throw exception if configured to and the API replies with a JSON hash containing a key called 'error'" do
200
- @gibbon.throws_exceptions = true
201
- allow(Gibbon::APICategory).to receive(:post).and_return(Struct.new(:body).new(MultiJson.dump({'error' => 'bad things'})))
202
- expect {@gibbon.say.hello}.to raise_error(Gibbon::MailChimpError)
203
- end
204
-
205
- it "not raise exception if the api returns no response body" do
206
- allow(Gibbon::APICategory).to receive(:post).and_return(Struct.new(:body).new(nil))
207
- expect(@gibbon.say.hello).to be_nil
208
- end
209
-
210
- it "can send a campaign" do
211
- allow(Gibbon::APICategory).to receive(:post).and_return(Struct.new(:body).new(MultiJson.dump({"cid" => "1234567"})))
212
- expect(@gibbon.campaigns.send({"cid" => "1234567"})).to eq({"cid" => "1234567"})
213
- end
214
-
215
- it "not throw exception if configured to and the API returns an unparsable response" do
216
- @gibbon.throws_exceptions = false
217
- allow(Gibbon::APICategory).to receive(:post).and_return(Struct.new(:body).new("<HTML>Invalid response</HTML>"))
218
- expect(@gibbon.say.hello).to eq({"name" => "UNPARSEABLE_RESPONSE", "error" => "Unparseable response: <HTML>Invalid response</HTML>", "code" => 500})
219
- end
220
-
221
- it "throw exception if configured to and the API returns an unparsable response" do
222
- @gibbon.throws_exceptions = true
223
- allow(Gibbon::APICategory).to receive(:post).and_return(Struct.new(:body).new("<HTML>Invalid response</HTML>"))
224
- expect{@gibbon.say.hello}.to raise_error(Gibbon::MailChimpError)
225
- end
226
- end
227
-
228
- describe "export API" do
229
- before do
230
- @key = "TESTKEY-us1"
231
- @gibbon = Gibbon::Export.new(@key)
232
- @url = "http://us1.api.mailchimp.com/export/1.0/"
233
- @body = {:apikey => @key, :id => "listid"}
234
- @return_items = ["array", "entries"]
235
- @returns = MultiJson.dump(@return_items)
236
- end
237
-
238
- it "handle api key with dc" do
239
- @api_key = "TESTKEY-us2"
240
- @gibbon = Gibbon::Export.new(@api_key)
241
-
242
- @body[:apikey] = @api_key
243
- url = @url.gsub('us1', 'us2') + "sayHello/"
244
-
245
- # Fake request
246
- stub_request(:post, url).
247
- to_return(:body => @returns, :status => 200)
248
-
249
- # Check request url
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
257
- end
258
-
259
- it "not throw exception if the Export API replies with a JSON hash containing a key called 'error'" do
260
- @gibbon.throws_exceptions = false
261
- reply = MultiJson.dump({:error => 'bad things'})
262
- stub_request(:post, @url + 'sayHello/').
263
- to_return(:body => reply, :status => 200)
264
-
265
- @gibbon.say_hello(@body)
266
- end
267
-
268
- it "throw exception if configured to and the Export API replies with a JSON hash containing a key called 'error'" do
269
- @gibbon.throws_exceptions = true
270
- reply = MultiJson.dump({:error => 'bad things', :code => '123'})
271
- stub_request(:post, @url + 'sayHello/').
272
- to_return(:body => reply, :status => 200)
273
-
274
- expect {@gibbon.say_hello(@body)}.to raise_error(Gibbon::MailChimpError)
275
- end
276
-
277
- it "should handle a single empty space response without throwing an exception" do
278
- @gibbon.throws_exceptions = true
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(" "))
282
-
283
- expect(@gibbon.say_hello(@body)).to eq([])
284
- end
285
-
286
- it "should handle an empty response without throwing an exception" do
287
- @gibbon.throws_exceptions = true
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(""))
291
-
292
- expect(@gibbon.say_hello(@body)).to eq([])
293
- end
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
-
307
- end
308
-
309
- private
310
-
311
- def expect_post(expected_url, expected_body, expected_timeout=30, expected_headers={})
312
- expect(Gibbon::APICategory).to receive(:post) { |url, opts|
313
- expect(url).to eq expected_url
314
- expect(expected_body).to eq MultiJson.load(URI::decode(opts[:body]))
315
- expect(opts[:timeout]).to eq expected_timeout
316
- expect(opts[:headers]).to eq expected_headers
317
- }.and_return(Struct.new(:body).new("[]"))
318
118
  end
319
119
  end
320
120
 
metadata CHANGED
@@ -1,43 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gibbon
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 2.0.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-07-31 00:00:00.000000000 Z
11
+ date: 2015-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: httparty
14
+ name: faraday
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: 0.9.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: 0.9.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: multi_json
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 1.9.0
33
+ version: 1.11.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 1.9.0
40
+ version: 1.11.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -58,15 +58,15 @@ dependencies:
58
58
  requirements:
59
59
  - - '='
60
60
  - !ruby/object:Gem::Version
61
- version: 3.1.0
61
+ version: 3.2.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.1.0
69
- description: A wrapper for MailChimp API 2.0 and Export API 1.0
68
+ version: 3.2.0
69
+ description: A wrapper for MailChimp API 3.0
70
70
  email:
71
71
  - amromousa@gmail.com
72
72
  executables: []
@@ -83,11 +83,10 @@ files:
83
83
  - Rakefile
84
84
  - gibbon.gemspec
85
85
  - lib/gibbon.rb
86
- - lib/gibbon/api.rb
87
- - lib/gibbon/api_category.rb
88
- - lib/gibbon/export.rb
86
+ - lib/gibbon/api_request.rb
89
87
  - lib/gibbon/gibbon_error.rb
90
88
  - lib/gibbon/mailchimp_error.rb
89
+ - lib/gibbon/request.rb
91
90
  - lib/gibbon/version.rb
92
91
  - spec/gibbon/gibbon_spec.rb
93
92
  - spec/spec_helper.rb
@@ -96,9 +95,9 @@ licenses:
96
95
  - MIT
97
96
  metadata: {}
98
97
  post_install_message: |-
99
- IMPORTANT: Gibbon now targets MailChimp API 2.0, which is substantially different from API 1.3.
100
- Please use Gibbon 0.4.6 if you need to use API 1.3.
101
- If you're upgrading from <0.5.0 your code WILL break.
98
+ IMPORTANT: Gibbon now targets MailChimp API 3.0, which is very different from API 2.0.
99
+ Please install Gibbon 1.2.0 if you need to use API 2.0.
100
+ Gibbon's API has changed substantially between versions 1.x and 2.x.
102
101
  rdoc_options: []
103
102
  require_paths:
104
103
  - lib
@@ -106,7 +105,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
106
105
  requirements:
107
106
  - - ">="
108
107
  - !ruby/object:Gem::Version
109
- version: '0'
108
+ version: 2.0.0
110
109
  required_rubygems_version: !ruby/object:Gem::Requirement
111
110
  requirements:
112
111
  - - ">="
@@ -117,7 +116,7 @@ rubyforge_project: gibbon
117
116
  rubygems_version: 2.4.6
118
117
  signing_key:
119
118
  specification_version: 4
120
- summary: A wrapper for MailChimp API 2.0 and Export API 1.0
119
+ summary: A wrapper for MailChimp API 3.0
121
120
  test_files:
122
121
  - spec/gibbon/gibbon_spec.rb
123
122
  - spec/spec_helper.rb