gibbon 0.3.5 → 0.4.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.
- data/.gitignore +49 -0
- data/.travis.yml +1 -1
- data/Gemfile +1 -13
- data/LICENSE.txt +1 -1
- data/README.markdown +73 -22
- data/Rakefile +4 -48
- data/gibbon.gemspec +24 -82
- data/lib/gibbon.rb +81 -72
- data/test/test_gibbon.rb +36 -18
- metadata +51 -94
- data/VERSION +0 -1
data/.gitignore
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# rcov generated
|
2
|
+
coverage
|
3
|
+
|
4
|
+
# rdoc generated
|
5
|
+
rdoc
|
6
|
+
|
7
|
+
# yard generated
|
8
|
+
doc
|
9
|
+
.yardoc
|
10
|
+
|
11
|
+
# bundler
|
12
|
+
.bundle
|
13
|
+
|
14
|
+
# jeweler generated
|
15
|
+
pkg
|
16
|
+
|
17
|
+
# Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
|
18
|
+
#
|
19
|
+
# * Create a file at ~/.gitignore
|
20
|
+
# * Include files you want ignored
|
21
|
+
# * Run: git config --global core.excludesfile ~/.gitignore
|
22
|
+
#
|
23
|
+
# After doing this, these files will be ignored in all your git projects,
|
24
|
+
# saving you from having to 'pollute' every project you touch with them
|
25
|
+
#
|
26
|
+
# Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
|
27
|
+
#
|
28
|
+
# For MacOS:
|
29
|
+
#
|
30
|
+
.DS_Store
|
31
|
+
#
|
32
|
+
# For TextMate
|
33
|
+
#*.tmproj
|
34
|
+
#tmtags
|
35
|
+
#
|
36
|
+
# For emacs:
|
37
|
+
#*~
|
38
|
+
#\#*
|
39
|
+
#.\#*
|
40
|
+
#
|
41
|
+
# For vim:
|
42
|
+
#*.swp
|
43
|
+
|
44
|
+
bin
|
45
|
+
cache
|
46
|
+
gems
|
47
|
+
specifications
|
48
|
+
Gemfile.lock
|
49
|
+
.rvmrc
|
data/.travis.yml
CHANGED
@@ -1 +1 @@
|
|
1
|
-
rvm: 1.9.
|
1
|
+
rvm: 1.9.3
|
data/Gemfile
CHANGED
@@ -1,15 +1,3 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
2
|
|
3
|
-
|
4
|
-
gem "httparty", "> 0.6.0"
|
5
|
-
gem "rdoc"
|
6
|
-
|
7
|
-
group :development, :test do
|
8
|
-
gem "shoulda", ">= 0"
|
9
|
-
gem "bundler", "~> 1.0.0"
|
10
|
-
gem "jeweler", "~> 1.5.1"
|
11
|
-
gem "rcov", ">= 0"
|
12
|
-
gem "mocha", "> 0.9.11"
|
13
|
-
gem "ruby-debug19", :require => "ruby-debug", :platforms => [:ruby_19]
|
14
|
-
gem "ruby-debug", :platforms => [:ruby_18]
|
15
|
-
end
|
3
|
+
gemspec
|
data/LICENSE.txt
CHANGED
data/README.markdown
CHANGED
@@ -1,9 +1,17 @@
|
|
1
1
|
# gibbon
|
2
2
|
|
3
|
-
Gibbon is a simple
|
3
|
+
Gibbon is a simple wrapper for MailChimp's [Primary and Export APIs](http://www.mailchimp.com/api).
|
4
4
|
|
5
5
|
[![Build Status](https://secure.travis-ci.org/amro/gibbon.png)](http://travis-ci.org/amro/gibbon)
|
6
6
|
|
7
|
+
##Important Notes About Version 0.4.0+
|
8
|
+
|
9
|
+
* Ruby 1.9.x+
|
10
|
+
* Errors are now raised by default
|
11
|
+
* Timeouts can be specified per request during initialization
|
12
|
+
* The environment variable 'MC_API_KEY' no longer works. Please use 'MAILCHIMP_API_KEY' instead.
|
13
|
+
* The code has been cleaned up a bit and a few more comments have been added
|
14
|
+
|
7
15
|
##Installation
|
8
16
|
|
9
17
|
$ gem install gibbon
|
@@ -20,15 +28,24 @@ You can create an instance of the API wrapper:
|
|
20
28
|
|
21
29
|
gb = Gibbon.new("your_api_key")
|
22
30
|
|
23
|
-
You can set
|
31
|
+
You can set `api_key`, `timeout` and `throws_exceptions` globally:
|
24
32
|
|
25
33
|
Gibbon.api_key = "your_api_key"
|
34
|
+
Gibbon.timeout = 15
|
35
|
+
Gibbon.throws_exceptions = false
|
36
|
+
|
37
|
+
For example, you could set the values above in an `initializer` file in your `Rails` app (e.g. your\_app/config/initializers/gibbon.rb).
|
38
|
+
|
39
|
+
Assuming you've set an `api_key` on Gibbon, you can conveniently make API calls on the class itself:
|
40
|
+
|
26
41
|
Gibbon.lists
|
27
42
|
|
28
|
-
You can also set the environment variable
|
43
|
+
You can also set the environment variable `MAILCHIMP_API_KEY` and Gibbon will use it when you create an instance:
|
29
44
|
|
30
45
|
u = Gibbon.new
|
31
46
|
|
47
|
+
> Note: In an effort to simplify Gibbon, the environment variable 'MC_API_KEY' is no longer available as of version 0.4.0. Please use 'MAILCHIMP_API_KEY' instead.
|
48
|
+
|
32
49
|
Fetching data is as simple as calling API methods directly on the wrapper
|
33
50
|
object. The API calls may be made with either camelcase or underscore
|
34
51
|
separated formatting as you see in the "More Advanced Examples" section below.
|
@@ -47,6 +64,10 @@ Similarly, to fetch your first 100 lists:
|
|
47
64
|
|
48
65
|
lists = gb.lists({:start => 0, :limit=> 100})
|
49
66
|
|
67
|
+
Or, to fetch a list by name:
|
68
|
+
|
69
|
+
list = gb.lists({:filters => {:list_name => list_name}})
|
70
|
+
|
50
71
|
### More Advanced Examples
|
51
72
|
|
52
73
|
Getting batch member information for subscribers looks like this:
|
@@ -57,6 +78,29 @@ or
|
|
57
78
|
|
58
79
|
info = gb.listMemberInfo({:id => list_id, :email_address => email_array})
|
59
80
|
|
81
|
+
List subscribers for a list:
|
82
|
+
|
83
|
+
gb.list_members({:id => list_id})
|
84
|
+
|
85
|
+
or
|
86
|
+
|
87
|
+
List unsubscribed members for a list
|
88
|
+
|
89
|
+
gb.list_members({:id => list_id, :status => "unsubscribed"})
|
90
|
+
|
91
|
+
Subscribe a member to a list:
|
92
|
+
|
93
|
+
gb.list_subscribe({:id => list_id, :email_address => "email_address", :merge_vars => {:FNAME => "First Name", :LNAME => "Last Name"}})
|
94
|
+
> Note: This will send a welcome email to the new subscriber
|
95
|
+
|
96
|
+
or
|
97
|
+
|
98
|
+
Batch subscribe members to a list:
|
99
|
+
|
100
|
+
gb.list_batch_subscribe(:id => list_id, :batch => [{:EMAIL => "email1", :FNAME => "FirstName1", :LNAME => "LastName1"},{:EMAIL => "email2", :FNAME => "FirstName2", :LNAME => "LastName2"}])
|
101
|
+
|
102
|
+
> Note: This will send welcome emails to the new subscribers
|
103
|
+
|
60
104
|
Fetch open and click detail for recipients of a particular campaign:
|
61
105
|
|
62
106
|
email_stats = gb.campaign_email_stats_aim({:cid => campaign_id, :email_address => email_array})
|
@@ -65,41 +109,47 @@ or
|
|
65
109
|
|
66
110
|
email_stats = gb.campaignEmailStatsAIM({:cid => campaign_id, :email_address => email_array})
|
67
111
|
|
68
|
-
###
|
112
|
+
### Setting timeouts
|
69
113
|
|
70
114
|
Gibbon defaults to a 30 second timeout. You can optionally set your own timeout (in seconds) like so:
|
71
115
|
|
72
|
-
gb.timeout
|
116
|
+
gb = Gibbon.new("your_api_key", {:timeout => 5})
|
117
|
+
|
118
|
+
or
|
119
|
+
|
120
|
+
gb.timeout = 5
|
121
|
+
|
122
|
+
### Error handling
|
123
|
+
|
124
|
+
By default Gibbon will attempt to raise errors returned by the API automatically.
|
125
|
+
|
126
|
+
If you set the `throws_exceptions` boolean attribute to false, for a given instance,
|
127
|
+
then Gibbon will not raise exceptions. This allows you to handle errors manually. The
|
128
|
+
APIs will return a Hash with two keys "errors", a string containing some textual
|
129
|
+
information about the error, and "code", the numeric code of the error.
|
130
|
+
|
131
|
+
> Note: In an effort to make Gibbon easier to use, errors are raised automatically as of version 0.4.0.
|
73
132
|
|
74
133
|
### Export API usage
|
75
134
|
|
76
|
-
In addition to the
|
77
|
-
[MailChimp Export API](http://apidocs.mailchimp.com/export/1.0/) using a GibbonExport object. Given an existing
|
78
|
-
Gibbon object you can request a new GibbonExporter object:
|
135
|
+
In addition to the primary API, you can make calls to the [Export API](http://apidocs.mailchimp.com/export/1.0/) using an instance of GibbonExport. Given an existing instance of Gibbon, you can request a new GibbonExporter object:
|
79
136
|
|
80
|
-
g = Gibbon.new(
|
137
|
+
g = Gibbon.new("your_api_key")
|
81
138
|
gibbon_export = g.get_exporter
|
82
139
|
|
83
140
|
or you can construct a new object directly:
|
84
141
|
|
85
|
-
gibbon_export = GibbonExport.new(
|
142
|
+
gibbon_export = GibbonExport.new("your_api_key")
|
86
143
|
|
87
144
|
Calling Export API functions is identical to making standard API calls but the
|
88
145
|
return value is an Enumerator which loops over the lines returned from the
|
89
146
|
Export API. This is because the data returned from the Export API is a stream
|
90
147
|
of JSON objects rather than a single JSON array.
|
91
148
|
|
92
|
-
### Error handling
|
93
|
-
|
94
|
-
By default you are expected to handle errors returned by the APIs manually. The
|
95
|
-
APIs will return a Hash with two keys "errors", a string containing some textual
|
96
|
-
information about the error, and "code", the numeric code of the error.
|
97
|
-
|
98
|
-
If you set the `throws_exceptions` boolean attribute for a given instance then
|
99
|
-
Gibbon will attempt to intercept the errors and raise an exception.
|
100
|
-
|
101
149
|
##Thanks
|
102
150
|
|
151
|
+
The following people have contributed to Gibbon's development in some way:
|
152
|
+
|
103
153
|
* [Justin Ip](https://github.com/ippy04)
|
104
154
|
* [elshimone](https://github.com/elshimone)
|
105
155
|
* [jlxw](https://github.com/jlxw)
|
@@ -108,9 +158,10 @@ Gibbon will attempt to intercept the errors and raise an exception.
|
|
108
158
|
* [Dave Worth](https://github.com/daveworth)
|
109
159
|
* [Mike Skalnik](https://github.com/skalnik)
|
110
160
|
* [Kristopher Murata](https://github.com/krsmurata)
|
161
|
+
* [Michael Klishin](https://github.com/michaelklishin)
|
111
162
|
* Rails for camelize gsub
|
112
163
|
|
113
|
-
##
|
164
|
+
##Copyright
|
114
165
|
|
115
|
-
* Copyright (c) 2010 Amro Mousa. See LICENSE.txt for details.
|
116
|
-
* MailChimp (c) 2001-
|
166
|
+
* Copyright (c) 2010-2012 Amro Mousa. See LICENSE.txt for details.
|
167
|
+
* MailChimp (c) 2001-2012 The Rocket Science Group.
|
data/Rakefile
CHANGED
@@ -1,54 +1,10 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'bundler'
|
3
|
-
begin
|
4
|
-
Bundler.setup(:default, :development)
|
5
|
-
rescue Bundler::BundlerError => e
|
6
|
-
$stderr.puts e.message
|
7
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
-
exit e.status_code
|
9
|
-
end
|
10
|
-
require 'rake'
|
11
|
-
|
12
|
-
require 'jeweler'
|
13
|
-
Jeweler::Tasks.new do |gem|
|
14
|
-
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
15
|
-
gem.name = "gibbon"
|
16
|
-
gem.homepage = "http://github.com/amro/gibbon"
|
17
|
-
gem.license = "MIT"
|
18
|
-
gem.summary = %Q{Gibbon is a simple API wrapper for interacting with MailChimp API 1.3}
|
19
|
-
gem.description = %Q{Gibbon is a simple API wrapper for interacting with MailChimp API version 1.3.}
|
20
|
-
gem.email = "amromousa@gmail.com"
|
21
|
-
gem.authors = ["Amro Mousa"]
|
22
|
-
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
23
|
-
# and development dependencies are only needed for development (ie running rake tasks, tests, etc)
|
24
|
-
gem.add_runtime_dependency 'httparty', '> 0.6.0'
|
25
|
-
gem.add_runtime_dependency 'json', '> 1.4.0'
|
26
|
-
gem.add_development_dependency 'mocha', '> 0.9.11'
|
27
|
-
end
|
28
|
-
Jeweler::RubygemsDotOrgTasks.new
|
29
|
-
|
30
1
|
require 'rake/testtask'
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
|
31
4
|
Rake::TestTask.new(:test) do |test|
|
32
5
|
test.libs << 'lib' << 'test'
|
33
|
-
test.pattern = 'test
|
6
|
+
test.pattern = 'test/test_*.rb'
|
34
7
|
test.verbose = true
|
35
8
|
end
|
36
9
|
|
37
|
-
|
38
|
-
Rcov::RcovTask.new do |test|
|
39
|
-
test.libs << 'test'
|
40
|
-
test.pattern = 'test/**/test_*.rb'
|
41
|
-
test.verbose = true
|
42
|
-
end
|
43
|
-
|
44
|
-
task :default => :test
|
45
|
-
|
46
|
-
require 'rdoc/task'
|
47
|
-
Rake::RDocTask.new do |rdoc|
|
48
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
49
|
-
|
50
|
-
rdoc.rdoc_dir = 'rdoc'
|
51
|
-
rdoc.title = "gibbon #{version}"
|
52
|
-
rdoc.rdoc_files.include('README*')
|
53
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
54
|
-
end
|
10
|
+
task default: [:test]
|
data/gibbon.gemspec
CHANGED
@@ -1,90 +1,32 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
5
3
|
|
6
4
|
Gem::Specification.new do |s|
|
7
|
-
s.name
|
8
|
-
s.version
|
5
|
+
s.name = "gibbon"
|
6
|
+
s.version = "0.4.0"
|
7
|
+
s.authors = ["Amro Mousa"]
|
8
|
+
s.email = ["amromousa@gmail.com"]
|
9
|
+
s.homepage = "http://github.com/amro/gibbon"
|
9
10
|
|
10
|
-
s.
|
11
|
-
s.
|
12
|
-
s.
|
13
|
-
|
14
|
-
s.
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
s.files
|
20
|
-
"
|
21
|
-
|
22
|
-
"Gemfile",
|
23
|
-
"LICENSE.txt",
|
24
|
-
"README.markdown",
|
25
|
-
"Rakefile",
|
26
|
-
"VERSION",
|
27
|
-
"gibbon.gemspec",
|
28
|
-
"lib/gibbon.rb",
|
29
|
-
"test/helper.rb",
|
30
|
-
"test/test_gibbon.rb"
|
31
|
-
]
|
32
|
-
s.homepage = "http://github.com/amro/gibbon"
|
33
|
-
s.licenses = ["MIT"]
|
11
|
+
s.summary = %q{A simple wrapper for MailChimp's primary and export APIs}
|
12
|
+
s.description = %q{A simple wrapper for MailChimp's primary and export APIs}
|
13
|
+
s.license = "MIT"
|
14
|
+
|
15
|
+
s.post_install_message = "Warning: Gibbon versions 0.4.0 and newer include breaking changes like throwing exceptions by default!\n" +
|
16
|
+
"Please read more at http://github.com/amro/gibbon before upgrading from 0.3.x!"
|
17
|
+
|
18
|
+
s.rubyforge_project = "gibbon"
|
19
|
+
|
20
|
+
s.files = `git ls-files`.split("\n")
|
21
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
22
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
34
23
|
s.require_paths = ["lib"]
|
35
|
-
s.rubygems_version = "1.8.10"
|
36
|
-
s.summary = "Gibbon is a simple API wrapper for interacting with MailChimp API 1.3"
|
37
|
-
s.test_files = [
|
38
|
-
"test/helper.rb",
|
39
|
-
"test/test_gibbon.rb"
|
40
|
-
]
|
41
24
|
|
42
|
-
|
43
|
-
|
25
|
+
s.add_dependency('httparty')
|
26
|
+
s.add_dependency('json')
|
44
27
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
50
|
-
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
51
|
-
s.add_development_dependency(%q<jeweler>, ["~> 1.5.1"])
|
52
|
-
s.add_development_dependency(%q<rcov>, [">= 0"])
|
53
|
-
s.add_development_dependency(%q<mocha>, ["> 0.9.11"])
|
54
|
-
s.add_development_dependency(%q<ruby-debug19>, [">= 0"])
|
55
|
-
s.add_development_dependency(%q<ruby-debug>, [">= 0"])
|
56
|
-
s.add_runtime_dependency(%q<httparty>, ["> 0.6.0"])
|
57
|
-
s.add_runtime_dependency(%q<json>, ["> 1.4.0"])
|
58
|
-
s.add_development_dependency(%q<mocha>, ["> 0.9.11"])
|
59
|
-
else
|
60
|
-
s.add_dependency(%q<json>, ["> 1.4.0"])
|
61
|
-
s.add_dependency(%q<httparty>, ["> 0.6.0"])
|
62
|
-
s.add_dependency(%q<rdoc>, [">= 0"])
|
63
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
64
|
-
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
65
|
-
s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
|
66
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
67
|
-
s.add_dependency(%q<mocha>, ["> 0.9.11"])
|
68
|
-
s.add_dependency(%q<ruby-debug19>, [">= 0"])
|
69
|
-
s.add_dependency(%q<ruby-debug>, [">= 0"])
|
70
|
-
s.add_dependency(%q<httparty>, ["> 0.6.0"])
|
71
|
-
s.add_dependency(%q<json>, ["> 1.4.0"])
|
72
|
-
s.add_dependency(%q<mocha>, ["> 0.9.11"])
|
73
|
-
end
|
74
|
-
else
|
75
|
-
s.add_dependency(%q<json>, ["> 1.4.0"])
|
76
|
-
s.add_dependency(%q<httparty>, ["> 0.6.0"])
|
77
|
-
s.add_dependency(%q<rdoc>, [">= 0"])
|
78
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
79
|
-
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
80
|
-
s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
|
81
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
82
|
-
s.add_dependency(%q<mocha>, ["> 0.9.11"])
|
83
|
-
s.add_dependency(%q<ruby-debug19>, [">= 0"])
|
84
|
-
s.add_dependency(%q<ruby-debug>, [">= 0"])
|
85
|
-
s.add_dependency(%q<httparty>, ["> 0.6.0"])
|
86
|
-
s.add_dependency(%q<json>, ["> 1.4.0"])
|
87
|
-
s.add_dependency(%q<mocha>, ["> 0.9.11"])
|
88
|
-
end
|
28
|
+
s.add_development_dependency('rake')
|
29
|
+
s.add_development_dependency('debugger')
|
30
|
+
s.add_development_dependency('shoulda')
|
31
|
+
s.add_development_dependency('mocha')
|
89
32
|
end
|
90
|
-
|
data/lib/gibbon.rb
CHANGED
@@ -6,126 +6,135 @@ class Gibbon
|
|
6
6
|
include HTTParty
|
7
7
|
format :plain
|
8
8
|
default_timeout 30
|
9
|
+
disable_rails_query_string_format
|
9
10
|
|
10
11
|
attr_accessor :api_key, :timeout, :throws_exceptions
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
@
|
16
|
-
end
|
13
|
+
MailChimpError = Class.new(StandardError)
|
14
|
+
|
15
|
+
def initialize(api_key = nil, default_parameters = {})
|
16
|
+
@api_key = api_key || self.class.api_key || ENV['MAILCHIMP_API_KEY']
|
17
17
|
|
18
|
+
@timeout = default_parameters.delete(:timeout)
|
19
|
+
@throws_exceptions = default_parameters.delete(:throws_exceptions)
|
20
|
+
|
21
|
+
@default_params = {apikey: @api_key}.merge(default_parameters)
|
22
|
+
|
23
|
+
set_instance_defaults
|
24
|
+
end
|
25
|
+
|
18
26
|
def api_key=(value)
|
19
27
|
@api_key = value
|
20
|
-
@default_params = @default_params.merge({:
|
28
|
+
@default_params = @default_params.merge({apikey: @api_key})
|
21
29
|
end
|
22
30
|
|
23
31
|
def get_exporter
|
24
32
|
GibbonExport.new(@api_key, @default_params)
|
25
33
|
end
|
26
34
|
|
35
|
+
protected
|
36
|
+
|
27
37
|
def base_api_url
|
28
38
|
"https://#{dc_from_api_key}api.mailchimp.com/1.3/?method="
|
29
39
|
end
|
30
|
-
|
31
|
-
protected
|
32
|
-
|
40
|
+
|
33
41
|
def call(method, params = {})
|
34
42
|
api_url = base_api_url + method
|
35
43
|
params = @default_params.merge(params)
|
36
|
-
response = self.class.post(api_url, :
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
44
|
+
response = self.class.post(api_url, body: CGI::escape(params.to_json), timeout: @timeout)
|
45
|
+
|
46
|
+
# MailChimp API sometimes returns JSON fragments (e.g. true from listSubscribe)
|
47
|
+
# so we parse after adding brackets to create a JSON array so
|
48
|
+
# JSON.parse succeeds in those cases.
|
49
|
+
parsed_response = JSON.parse('[' + response.body + ']').first
|
50
|
+
|
51
|
+
if should_raise_for_response?(parsed_response)
|
52
|
+
raise MailChimpError.new("MailChimp API Error: #{parsed_response["error"]} (code #{parsed_response["code"]})")
|
42
53
|
end
|
43
54
|
|
44
|
-
|
45
|
-
|
46
|
-
|
55
|
+
# Some calls (e.g. listSubscribe) return json fragments
|
56
|
+
# (e.g. true) so wrap in an array prior to parsing
|
57
|
+
response = JSON.parse('['+response.body+']').first
|
47
58
|
|
48
|
-
|
59
|
+
parsed_response
|
49
60
|
end
|
50
|
-
|
61
|
+
|
51
62
|
def method_missing(method, *args)
|
52
|
-
|
63
|
+
# To support underscores, we camelize the method name
|
64
|
+
|
65
|
+
# Thanks for the camelize gsub, Rails
|
66
|
+
method = method.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
|
67
|
+
|
68
|
+
# We need to downcase the first letter of every API method
|
69
|
+
# and MailChimp has a few of API methods that end in "AIM," which
|
70
|
+
# must be upcased (See "Campaign Report Data Methods" in their API docs).
|
53
71
|
method = method[0].chr.downcase + method[1..-1].gsub(/aim$/i, 'AIM')
|
54
|
-
|
55
|
-
|
56
|
-
|
72
|
+
|
73
|
+
call(method, *args)
|
74
|
+
end
|
75
|
+
|
76
|
+
def set_instance_defaults
|
77
|
+
@timeout = (self.class.timeout || 30) if @timeout.nil?
|
78
|
+
|
79
|
+
# Two lines because the class variable could be false and (false || true) is always true
|
80
|
+
@throws_exceptions = self.class.throws_exceptions if @throws_exceptions.nil?
|
81
|
+
@throws_exceptions = true if @throws_exceptions.nil?
|
82
|
+
end
|
83
|
+
|
84
|
+
def should_raise_for_response?(response)
|
85
|
+
@throws_exceptions && response.is_a?(Hash) && response["error"]
|
86
|
+
end
|
87
|
+
|
88
|
+
def base_api_url
|
89
|
+
"https://#{get_data_center_from_api_key}api.mailchimp.com/1.3/?method="
|
57
90
|
end
|
58
91
|
|
59
92
|
class << self
|
60
|
-
attr_accessor :api_key
|
93
|
+
attr_accessor :api_key, :timeout, :throws_exceptions
|
61
94
|
|
62
95
|
def method_missing(sym, *args, &block)
|
63
|
-
new(self.api_key).send(sym, *args, &block)
|
96
|
+
new(self.api_key, {timeout: self.timeout, throws_exceptions: self.throws_exceptions}).send(sym, *args, &block)
|
64
97
|
end
|
65
98
|
end
|
66
99
|
|
67
|
-
def
|
68
|
-
|
100
|
+
def get_data_center_from_api_key
|
101
|
+
# Return an empty string for invalid API keys so Gibbon hits the main endpoint
|
102
|
+
data_center = ""
|
103
|
+
|
104
|
+
if (@api_key && @api_key["-"])
|
105
|
+
# Add a period since the data_center is a subdomain and it keeps things dry
|
106
|
+
data_center = "#{@api_key.split('-').last}."
|
107
|
+
end
|
108
|
+
|
109
|
+
data_center
|
69
110
|
end
|
70
111
|
end
|
71
|
-
|
112
|
+
|
72
113
|
class GibbonExport < Gibbon
|
73
|
-
def initialize(api_key = nil,
|
74
|
-
super(api_key,
|
114
|
+
def initialize(api_key = nil, default_parameters = {})
|
115
|
+
super(api_key, default_parameters)
|
75
116
|
end
|
76
117
|
|
77
|
-
protected
|
118
|
+
protected
|
78
119
|
|
79
120
|
def export_api_url
|
80
|
-
"http://#{
|
121
|
+
"http://#{get_data_center_from_api_key}api.mailchimp.com/export/1.0/"
|
81
122
|
end
|
82
123
|
|
83
124
|
def call(method, params = {})
|
84
125
|
api_url = export_api_url + method + "/"
|
85
126
|
params = @default_params.merge(params)
|
86
|
-
response = self.class.post(api_url, :
|
127
|
+
response = self.class.post(api_url, body: params, timeout: @timeout)
|
87
128
|
|
88
129
|
lines = response.body.lines
|
89
130
|
if @throws_exceptions
|
90
|
-
|
91
|
-
|
131
|
+
first_line = JSON.parse(lines.first) if lines.first
|
132
|
+
|
133
|
+
if should_raise_for_response?(first_line)
|
134
|
+
raise MailChimpError.new("MailChimp Export API Error: #{first_line["error"]} (code #{first_line["code"]})")
|
135
|
+
end
|
92
136
|
end
|
93
137
|
|
94
138
|
lines
|
95
139
|
end
|
96
|
-
end
|
97
|
-
|
98
|
-
module HTTParty
|
99
|
-
module HashConversions
|
100
|
-
# @param key<Object> The key for the param.
|
101
|
-
# @param value<Object> The value for the param.
|
102
|
-
#
|
103
|
-
# @return <String> This key value pair as a param
|
104
|
-
#
|
105
|
-
# @example normalize_param(:name, "Bob Jones") #=> "name=Bob%20Jones&"
|
106
|
-
def self.normalize_param(key, value)
|
107
|
-
param = ''
|
108
|
-
stack = []
|
109
|
-
|
110
|
-
if value.is_a?(Array)
|
111
|
-
param << Hash[*(0...value.length).to_a.zip(value).flatten].map {|i,element| normalize_param("#{key}[#{i}]", element)}.join
|
112
|
-
elsif value.is_a?(Hash)
|
113
|
-
stack << [key,value]
|
114
|
-
else
|
115
|
-
param << "#{key}=#{URI.encode(value.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}&"
|
116
|
-
end
|
117
|
-
|
118
|
-
stack.each do |parent, hash|
|
119
|
-
hash.each do |key, value|
|
120
|
-
if value.is_a?(Hash)
|
121
|
-
stack << ["#{parent}[#{key}]", value]
|
122
|
-
else
|
123
|
-
param << normalize_param("#{parent}[#{key}]", value)
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
param
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
140
|
+
end
|
data/test/test_gibbon.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'helper'
|
2
2
|
require 'cgi'
|
3
|
-
require 'ruby-debug'
|
3
|
+
require 'ruby-debug' unless ENV["CI"]
|
4
4
|
|
5
5
|
class TestGibbon < Test::Unit::TestCase
|
6
6
|
|
@@ -20,13 +20,6 @@ class TestGibbon < Test::Unit::TestCase
|
|
20
20
|
assert_equal(@api_key, @gibbon.api_key)
|
21
21
|
end
|
22
22
|
|
23
|
-
should "set an API key from the 'MC_API_KEY' ENV variable" do
|
24
|
-
ENV['MC_API_KEY'] = @api_key
|
25
|
-
@gibbon = Gibbon.new
|
26
|
-
assert_equal(@api_key, @gibbon.api_key)
|
27
|
-
ENV.delete('MC_API_KEY')
|
28
|
-
end
|
29
|
-
|
30
23
|
should "set an API key from the 'MAILCHIMP_API_KEY' ENV variable" do
|
31
24
|
ENV['MAILCHIMP_API_KEY'] = @api_key
|
32
25
|
@gibbon = Gibbon.new
|
@@ -79,6 +72,32 @@ class TestGibbon < Test::Unit::TestCase
|
|
79
72
|
@gibbon.say_hello
|
80
73
|
end
|
81
74
|
end
|
75
|
+
|
76
|
+
context "Gibbon class variables" do
|
77
|
+
setup do
|
78
|
+
Gibbon.api_key = "123-us1"
|
79
|
+
Gibbon.timeout = 15
|
80
|
+
Gibbon.throws_exceptions = false
|
81
|
+
end
|
82
|
+
|
83
|
+
teardown do
|
84
|
+
Gibbon.api_key = nil
|
85
|
+
Gibbon.timeout = nil
|
86
|
+
Gibbon.throws_exceptions = nil
|
87
|
+
end
|
88
|
+
|
89
|
+
should "set api key on new instances" do
|
90
|
+
assert_equal(Gibbon.new.api_key, Gibbon.api_key)
|
91
|
+
end
|
92
|
+
|
93
|
+
should "set timeout on new instances" do
|
94
|
+
assert_equal(Gibbon.new.timeout, Gibbon.timeout)
|
95
|
+
end
|
96
|
+
|
97
|
+
should "set throws_exceptions on new instances" do
|
98
|
+
assert_equal(Gibbon.new.throws_exceptions, Gibbon.throws_exceptions)
|
99
|
+
end
|
100
|
+
end
|
82
101
|
|
83
102
|
context "build api body" do
|
84
103
|
setup do
|
@@ -129,19 +148,18 @@ class TestGibbon < Test::Unit::TestCase
|
|
129
148
|
assert_equal(@exporter.api_key, @gibbon.api_key)
|
130
149
|
end
|
131
150
|
|
132
|
-
should "throw exception if configured to and the API replies with a JSON hash containing a key called 'error'" do
|
151
|
+
should "not throw exception if configured to and the API replies with a JSON hash containing a key called 'error'" do
|
152
|
+
@gibbon.throws_exceptions = false
|
133
153
|
Gibbon.stubs(:post).returns(Struct.new(:body).new({'error' => 'bad things'}.to_json))
|
134
154
|
assert_nothing_raised do
|
135
|
-
|
155
|
+
@gibbon.say_hello
|
136
156
|
end
|
137
|
-
|
138
|
-
ap result
|
139
157
|
end
|
140
158
|
|
141
159
|
should "throw exception if configured to and the API replies with a JSON hash containing a key called 'error'" do
|
142
160
|
@gibbon.throws_exceptions = true
|
143
161
|
Gibbon.stubs(:post).returns(Struct.new(:body).new({'error' => 'bad things'}.to_json))
|
144
|
-
assert_raise
|
162
|
+
assert_raise Gibbon::MailChimpError do
|
145
163
|
@gibbon.say_hello
|
146
164
|
end
|
147
165
|
end
|
@@ -160,7 +178,7 @@ class TestGibbon < Test::Unit::TestCase
|
|
160
178
|
@api_key = "TESTKEY-us2"
|
161
179
|
@gibbon = GibbonExport.new(@api_key)
|
162
180
|
|
163
|
-
params = {:body => @body, :timeout =>
|
181
|
+
params = {:body => @body, :timeout => 30}
|
164
182
|
|
165
183
|
url = @url.gsub('us1', 'us2') + "sayHello/"
|
166
184
|
GibbonExport.expects(:post).with(url, params).returns(@returns)
|
@@ -168,6 +186,7 @@ class TestGibbon < Test::Unit::TestCase
|
|
168
186
|
end
|
169
187
|
|
170
188
|
should "not throw exception if the Export API replies with a JSON hash containing a key called 'error'" do
|
189
|
+
@gibbon.throws_exceptions = false
|
171
190
|
GibbonExport.stubs(:post).returns(Struct.new(:body).new({'error' => 'bad things'}.to_json))
|
172
191
|
|
173
192
|
assert_nothing_raised do
|
@@ -177,10 +196,10 @@ class TestGibbon < Test::Unit::TestCase
|
|
177
196
|
|
178
197
|
should "throw exception if configured to and the Export API replies with a JSON hash containing a key called 'error'" do
|
179
198
|
@gibbon.throws_exceptions = true
|
180
|
-
params = {:body => @body, :timeout =>
|
199
|
+
params = {:body => @body, :timeout => 30}
|
181
200
|
GibbonExport.stubs(:post).returns(Struct.new(:body).new({'error' => 'bad things', 'code' => '123'}.to_json))
|
182
201
|
|
183
|
-
assert_raise
|
202
|
+
assert_raise Gibbon::MailChimpError do
|
184
203
|
@gibbon.say_hello(@body)
|
185
204
|
end
|
186
205
|
end
|
@@ -189,12 +208,11 @@ class TestGibbon < Test::Unit::TestCase
|
|
189
208
|
|
190
209
|
private
|
191
210
|
|
192
|
-
def expect_post(expected_url, expected_body, expected_timeout=
|
211
|
+
def expect_post(expected_url, expected_body, expected_timeout=30)
|
193
212
|
Gibbon.expects(:post).with do |url, opts|
|
194
213
|
url == expected_url &&
|
195
214
|
JSON.parse(URI::decode(opts[:body])) == expected_body &&
|
196
215
|
opts[:timeout] == expected_timeout
|
197
216
|
end.returns(Struct.new(:body).new("") )
|
198
217
|
end
|
199
|
-
|
200
218
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gibbon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,110 +9,75 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2012-11-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
-
- !ruby/object:Gem::Dependency
|
15
|
-
name: json
|
16
|
-
requirement: &70215916804420 !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
|
-
requirements:
|
19
|
-
- - ! '>'
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version: 1.4.0
|
22
|
-
type: :runtime
|
23
|
-
prerelease: false
|
24
|
-
version_requirements: *70215916804420
|
25
14
|
- !ruby/object:Gem::Dependency
|
26
15
|
name: httparty
|
27
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
28
17
|
none: false
|
29
18
|
requirements:
|
30
|
-
- - ! '
|
19
|
+
- - ! '>='
|
31
20
|
- !ruby/object:Gem::Version
|
32
|
-
version: 0
|
21
|
+
version: '0'
|
33
22
|
type: :runtime
|
34
23
|
prerelease: false
|
35
|
-
version_requirements:
|
36
|
-
- !ruby/object:Gem::Dependency
|
37
|
-
name: rdoc
|
38
|
-
requirement: &70215916803380 !ruby/object:Gem::Requirement
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
25
|
none: false
|
40
26
|
requirements:
|
41
27
|
- - ! '>='
|
42
28
|
- !ruby/object:Gem::Version
|
43
29
|
version: '0'
|
44
|
-
type: :runtime
|
45
|
-
prerelease: false
|
46
|
-
version_requirements: *70215916803380
|
47
30
|
- !ruby/object:Gem::Dependency
|
48
|
-
name:
|
49
|
-
requirement:
|
31
|
+
name: json
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
50
33
|
none: false
|
51
34
|
requirements:
|
52
35
|
- - ! '>='
|
53
36
|
- !ruby/object:Gem::Version
|
54
37
|
version: '0'
|
55
|
-
type: :
|
38
|
+
type: :runtime
|
56
39
|
prerelease: false
|
57
|
-
version_requirements:
|
58
|
-
- !ruby/object:Gem::Dependency
|
59
|
-
name: bundler
|
60
|
-
requirement: &70215916802360 !ruby/object:Gem::Requirement
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
61
41
|
none: false
|
62
42
|
requirements:
|
63
|
-
- -
|
43
|
+
- - ! '>='
|
64
44
|
- !ruby/object:Gem::Version
|
65
|
-
version:
|
66
|
-
type: :development
|
67
|
-
prerelease: false
|
68
|
-
version_requirements: *70215916802360
|
45
|
+
version: '0'
|
69
46
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
71
|
-
requirement:
|
47
|
+
name: rake
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
72
49
|
none: false
|
73
50
|
requirements:
|
74
|
-
- -
|
51
|
+
- - ! '>='
|
75
52
|
- !ruby/object:Gem::Version
|
76
|
-
version:
|
53
|
+
version: '0'
|
77
54
|
type: :development
|
78
55
|
prerelease: false
|
79
|
-
version_requirements:
|
80
|
-
- !ruby/object:Gem::Dependency
|
81
|
-
name: rcov
|
82
|
-
requirement: &70215916801380 !ruby/object:Gem::Requirement
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
83
57
|
none: false
|
84
58
|
requirements:
|
85
59
|
- - ! '>='
|
86
60
|
- !ruby/object:Gem::Version
|
87
61
|
version: '0'
|
88
|
-
type: :development
|
89
|
-
prerelease: false
|
90
|
-
version_requirements: *70215916801380
|
91
62
|
- !ruby/object:Gem::Dependency
|
92
|
-
name:
|
93
|
-
requirement:
|
63
|
+
name: debugger
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
94
65
|
none: false
|
95
66
|
requirements:
|
96
|
-
- - ! '
|
67
|
+
- - ! '>='
|
97
68
|
- !ruby/object:Gem::Version
|
98
|
-
version: 0
|
69
|
+
version: '0'
|
99
70
|
type: :development
|
100
71
|
prerelease: false
|
101
|
-
version_requirements:
|
102
|
-
- !ruby/object:Gem::Dependency
|
103
|
-
name: ruby-debug19
|
104
|
-
requirement: &70215916800320 !ruby/object:Gem::Requirement
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
73
|
none: false
|
106
74
|
requirements:
|
107
75
|
- - ! '>='
|
108
76
|
- !ruby/object:Gem::Version
|
109
77
|
version: '0'
|
110
|
-
type: :development
|
111
|
-
prerelease: false
|
112
|
-
version_requirements: *70215916800320
|
113
78
|
- !ruby/object:Gem::Dependency
|
114
|
-
name:
|
115
|
-
requirement:
|
79
|
+
name: shoulda
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
116
81
|
none: false
|
117
82
|
requirements:
|
118
83
|
- - ! '>='
|
@@ -120,56 +85,42 @@ dependencies:
|
|
120
85
|
version: '0'
|
121
86
|
type: :development
|
122
87
|
prerelease: false
|
123
|
-
version_requirements:
|
124
|
-
- !ruby/object:Gem::Dependency
|
125
|
-
name: httparty
|
126
|
-
requirement: &70215916799260 !ruby/object:Gem::Requirement
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
127
89
|
none: false
|
128
90
|
requirements:
|
129
|
-
- - ! '
|
91
|
+
- - ! '>='
|
130
92
|
- !ruby/object:Gem::Version
|
131
|
-
version: 0
|
132
|
-
type: :runtime
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: *70215916799260
|
93
|
+
version: '0'
|
135
94
|
- !ruby/object:Gem::Dependency
|
136
|
-
name:
|
137
|
-
requirement:
|
95
|
+
name: mocha
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
138
97
|
none: false
|
139
98
|
requirements:
|
140
|
-
- - ! '
|
99
|
+
- - ! '>='
|
141
100
|
- !ruby/object:Gem::Version
|
142
|
-
version:
|
143
|
-
type: :
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
144
103
|
prerelease: false
|
145
|
-
version_requirements:
|
146
|
-
- !ruby/object:Gem::Dependency
|
147
|
-
name: mocha
|
148
|
-
requirement: &70215916798280 !ruby/object:Gem::Requirement
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
105
|
none: false
|
150
106
|
requirements:
|
151
|
-
- - ! '
|
107
|
+
- - ! '>='
|
152
108
|
- !ruby/object:Gem::Version
|
153
|
-
version: 0
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
description: Gibbon is a simple API wrapper for interacting with MailChimp API version
|
158
|
-
1.3.
|
159
|
-
email: amromousa@gmail.com
|
109
|
+
version: '0'
|
110
|
+
description: A simple wrapper for MailChimp's primary and export APIs
|
111
|
+
email:
|
112
|
+
- amromousa@gmail.com
|
160
113
|
executables: []
|
161
114
|
extensions: []
|
162
|
-
extra_rdoc_files:
|
163
|
-
- LICENSE.txt
|
164
|
-
- README.markdown
|
115
|
+
extra_rdoc_files: []
|
165
116
|
files:
|
166
117
|
- .document
|
118
|
+
- .gitignore
|
167
119
|
- .travis.yml
|
168
120
|
- Gemfile
|
169
121
|
- LICENSE.txt
|
170
122
|
- README.markdown
|
171
123
|
- Rakefile
|
172
|
-
- VERSION
|
173
124
|
- gibbon.gemspec
|
174
125
|
- lib/gibbon.rb
|
175
126
|
- test/helper.rb
|
@@ -177,7 +128,10 @@ files:
|
|
177
128
|
homepage: http://github.com/amro/gibbon
|
178
129
|
licenses:
|
179
130
|
- MIT
|
180
|
-
post_install_message:
|
131
|
+
post_install_message: ! 'Warning: Gibbon versions 0.4.0 and newer include breaking
|
132
|
+
changes like throwing exceptions by default!
|
133
|
+
|
134
|
+
Please read more at http://github.com/amro/gibbon before upgrading from 0.3.x!'
|
181
135
|
rdoc_options: []
|
182
136
|
require_paths:
|
183
137
|
- lib
|
@@ -189,19 +143,22 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
189
143
|
version: '0'
|
190
144
|
segments:
|
191
145
|
- 0
|
192
|
-
hash:
|
146
|
+
hash: -1069299748253036727
|
193
147
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
194
148
|
none: false
|
195
149
|
requirements:
|
196
150
|
- - ! '>='
|
197
151
|
- !ruby/object:Gem::Version
|
198
152
|
version: '0'
|
153
|
+
segments:
|
154
|
+
- 0
|
155
|
+
hash: -1069299748253036727
|
199
156
|
requirements: []
|
200
|
-
rubyforge_project:
|
201
|
-
rubygems_version: 1.8.
|
157
|
+
rubyforge_project: gibbon
|
158
|
+
rubygems_version: 1.8.24
|
202
159
|
signing_key:
|
203
160
|
specification_version: 3
|
204
|
-
summary:
|
161
|
+
summary: A simple wrapper for MailChimp's primary and export APIs
|
205
162
|
test_files:
|
206
163
|
- test/helper.rb
|
207
164
|
- test/test_gibbon.rb
|
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
0.3.5
|