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 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.2
1
+ rvm: 1.9.3
data/Gemfile CHANGED
@@ -1,15 +1,3 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- gem "json", "> 1.4.0"
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
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010 Amro Mousa
1
+ Copyright (c) 2010-2012 Amro Mousa
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.markdown CHANGED
@@ -1,9 +1,17 @@
1
1
  # gibbon
2
2
 
3
- Gibbon is a simple API wrapper for interacting with [MailChimp API](http://www.mailchimp.com/api) 1.3.
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 your api_key globally and call class methods:
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 'MC_API_KEY' and Gibbon will use it when you create an instance:
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
- ### Other Stuff
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 = 5
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 standard API you can make calls 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(@api_key)
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(@api_key)
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
- ##Copyrights
164
+ ##Copyright
114
165
 
115
- * Copyright (c) 2010 Amro Mousa. See LICENSE.txt for details.
116
- * MailChimp (c) 2001-2010 The Rocket Science Group.
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/**/test_*.rb'
6
+ test.pattern = 'test/test_*.rb'
34
7
  test.verbose = true
35
8
  end
36
9
 
37
- require 'rcov/rcovtask'
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 = "gibbon"
8
- s.version = "0.3.5"
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.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Amro Mousa"]
12
- s.date = "2011-12-09"
13
- s.description = "Gibbon is a simple API wrapper for interacting with MailChimp API version 1.3."
14
- s.email = "amromousa@gmail.com"
15
- s.extra_rdoc_files = [
16
- "LICENSE.txt",
17
- "README.markdown"
18
- ]
19
- s.files = [
20
- ".document",
21
- ".travis.yml",
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
- if s.respond_to? :specification_version then
43
- s.specification_version = 3
25
+ s.add_dependency('httparty')
26
+ s.add_dependency('json')
44
27
 
45
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
46
- s.add_runtime_dependency(%q<json>, ["> 1.4.0"])
47
- s.add_runtime_dependency(%q<httparty>, ["> 0.6.0"])
48
- s.add_runtime_dependency(%q<rdoc>, [">= 0"])
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
- def initialize(api_key = nil, extra_params = {})
13
- @api_key = api_key || ENV['MC_API_KEY'] || ENV['MAILCHIMP_API_KEY'] || self.class.api_key
14
- @default_params = {:apikey => @api_key}.merge(extra_params)
15
- @throws_exceptions = false
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({:apikey => @api_key})
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, :body => CGI::escape(params.to_json), :timeout => @timeout)
37
-
38
- begin
39
- response = JSON.parse(response.body)
40
- rescue
41
- response = JSON.parse('['+response.body+']').first
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
- if @throws_exceptions && response.is_a?(Hash) && response["error"]
45
- raise "Error from MailChimp API: #{response["error"]} (code #{response["code"]})"
46
- end
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
- response
59
+ parsed_response
49
60
  end
50
-
61
+
51
62
  def method_missing(method, *args)
52
- method = method.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase } #Thanks for the gsub, Rails
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
- args = {} unless args.length > 0
55
- args = args[0] if args.is_a?(Array)
56
- call(method, args)
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 dc_from_api_key
68
- (@api_key.nil? || @api_key.length == 0 || @api_key !~ /-/) ? '' : "#{@api_key.split("-").last}."
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, extra_params = {})
74
- super(api_key, extra_params)
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://#{dc_from_api_key}api.mailchimp.com/export/1.0/"
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, :body => params, :timeout => @timeout)
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
- first_line_object = JSON.parse(lines.first) if lines.first
91
- raise "Error from MailChimp Export API: #{first_line_object["error"]} (code #{first_line_object["code"]})" if first_line_object.is_a?(Hash) && first_line_object["error"]
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
- result = @gibbon.say_hello
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 RuntimeError do
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 => nil}
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 => nil}
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 RuntimeError do
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=nil)
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.3.5
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: 2011-12-09 00:00:00.000000000Z
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: &70215916803880 !ruby/object:Gem::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.6.0
21
+ version: '0'
33
22
  type: :runtime
34
23
  prerelease: false
35
- version_requirements: *70215916803880
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: shoulda
49
- requirement: &70215916802860 !ruby/object:Gem::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: :development
38
+ type: :runtime
56
39
  prerelease: false
57
- version_requirements: *70215916802860
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: 1.0.0
66
- type: :development
67
- prerelease: false
68
- version_requirements: *70215916802360
45
+ version: '0'
69
46
  - !ruby/object:Gem::Dependency
70
- name: jeweler
71
- requirement: &70215916801880 !ruby/object:Gem::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: 1.5.1
53
+ version: '0'
77
54
  type: :development
78
55
  prerelease: false
79
- version_requirements: *70215916801880
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: mocha
93
- requirement: &70215916800900 !ruby/object:Gem::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.9.11
69
+ version: '0'
99
70
  type: :development
100
71
  prerelease: false
101
- version_requirements: *70215916800900
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: ruby-debug
115
- requirement: &70215916799820 !ruby/object:Gem::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: *70215916799820
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.6.0
132
- type: :runtime
133
- prerelease: false
134
- version_requirements: *70215916799260
93
+ version: '0'
135
94
  - !ruby/object:Gem::Dependency
136
- name: json
137
- requirement: &70215916798760 !ruby/object:Gem::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: 1.4.0
143
- type: :runtime
101
+ version: '0'
102
+ type: :development
144
103
  prerelease: false
145
- version_requirements: *70215916798760
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.9.11
154
- type: :development
155
- prerelease: false
156
- version_requirements: *70215916798280
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: 2484681847014778233
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.10
157
+ rubyforge_project: gibbon
158
+ rubygems_version: 1.8.24
202
159
  signing_key:
203
160
  specification_version: 3
204
- summary: Gibbon is a simple API wrapper for interacting with MailChimp API 1.3
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