babney-hominid 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/LICENSE +20 -0
- data/README.textile +161 -0
- data/Rakefile +57 -0
- data/VERSION +1 -0
- data/hominid.gemspec +60 -0
- data/hominid.yml.tpl +25 -0
- data/lib/hominid.rb +54 -0
- data/lib/hominid/base.rb +90 -0
- data/lib/hominid/campaign.rb +172 -0
- data/lib/hominid/helper.rb +45 -0
- data/lib/hominid/list.rb +150 -0
- data/lib/hominid/webhook.rb +131 -0
- data/tasks/rails/hominid.rake +22 -0
- data/test/hominid_test.rb +7 -0
- data/test/test_helper.rb +10 -0
- metadata +82 -0
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Brian Getting
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.textile
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
h1. Hominid
|
2
|
+
|
3
|
+
Hominid is a Ruby gem that provides a wrapper for interacting with the "Mailchimp":http://www.mailchimp.com email marketing service API ("version 1.2":http://www.mailchimp.com/api/1.2/).
|
4
|
+
|
5
|
+
h2. Installation
|
6
|
+
|
7
|
+
<pre><code>sudo gem install hominid, :version => '>= 2.0.1', :source => "http://gemcutter.org"</code></pre>
|
8
|
+
|
9
|
+
Hominid is hosted at "Gemcutter":http://gemcutter.org. Be sure that you have the Gemcutter gem installed if you are having trouble installing Hominid:
|
10
|
+
|
11
|
+
<pre><code>sudo gem install gemcutter
|
12
|
+
gem tumble</code></pre>
|
13
|
+
|
14
|
+
h2. Configuration
|
15
|
+
|
16
|
+
You will need to create a "Mailchimp":http://www.mailchimp.com/signup account and get your API key (available at http://admin.mailchimp.com/account/api/) in order to get started.
|
17
|
+
|
18
|
+
If you are using Hominid inside a Rails application, you can create a config file at @/config/hominid.yml@ with your Mailchimp account information and basic configuration options:
|
19
|
+
|
20
|
+
<pre><code>development:
|
21
|
+
username: USERNAME
|
22
|
+
password: PASSWORD
|
23
|
+
api_key: API KEY
|
24
|
+
send_goodbye: false
|
25
|
+
send_notify: false
|
26
|
+
double_opt: false
|
27
|
+
|
28
|
+
...</code></pre>
|
29
|
+
|
30
|
+
Run @rake hominid:config@ from within a Rails app to create an empty config file.
|
31
|
+
Note: You will need to <pre><code>require 'hominid'</code></pre> in your @Rakefile@ to make this rake task available to your application.
|
32
|
+
|
33
|
+
h2. Usage
|
34
|
+
|
35
|
+
Not all API methods are supported (yet). Currently there are classes for working with lists (_Hominid::List_), campaigns (_Hominid::Campaign_) and accessing the helper methods (_Hominid::Helper_).
|
36
|
+
|
37
|
+
h3. Working with Lists
|
38
|
+
|
39
|
+
The _Hominid::List_ class is available for working finding lists and working with particular lists. See _Hominid::List_ for more information.
|
40
|
+
|
41
|
+
h4. List Finder Methods
|
42
|
+
|
43
|
+
There are finder methods for working with lists. Refer to _Hominid::List_ to see the other finders availables.
|
44
|
+
|
45
|
+
<pre><code>lists = Hominid::List.all</code></pre>
|
46
|
+
|
47
|
+
<pre><code>list = Hominid::List.find_by_name("List Name")</code></pre>
|
48
|
+
|
49
|
+
<pre><code>list = Hominid::List.find(id_or_web_id)</code></pre>
|
50
|
+
|
51
|
+
h4. Subscribing
|
52
|
+
|
53
|
+
To subscribe a person or persons to a Mailchimp list:
|
54
|
+
|
55
|
+
<pre><code>list.subscribe("sample@emailaddress.com")</code></pre>
|
56
|
+
|
57
|
+
<pre><code>list.subscribe_many([{:EMAIL => 'sample@emailaddress.com', :EMAIL_TYPE => 'html'}, {:EMAIL => 'another@emailaddress.com', :EMAIL_TYPE => 'html'}])</code></pre>
|
58
|
+
|
59
|
+
h4. Unsubscribing
|
60
|
+
|
61
|
+
To unsubscribe a person or persons from a Mailchimp list:
|
62
|
+
|
63
|
+
<pre><code>list.unsubscribe("sample@emailaddress.com")</code></pre>
|
64
|
+
|
65
|
+
<pre><code>list.unsubscribe_many(['sample@emailaddress.com', 'another@emailaddress.com'])</code></pre>
|
66
|
+
|
67
|
+
h4. Updating
|
68
|
+
|
69
|
+
In the following example, we will be changing a person's email address on the Mailchimp list from @sample@ to @another@:
|
70
|
+
|
71
|
+
<pre><code>list.update_member('sample@emailaddress.com', {:EMAIL => 'another@emailaddress.com'}, 'html')</code></pre>
|
72
|
+
|
73
|
+
You can also updated other attributes by including the MERGE_VARS that you want to change, such as @EMAIL@, @FNAME@, @LNAME@ and @INTERESTS@. Get a list of merge tags for a particular list by running @list.merge_tags@.
|
74
|
+
|
75
|
+
h3. Working with Campaigns
|
76
|
+
|
77
|
+
The _Hominid::Campaign_ class provides methods for working with a campaigns.
|
78
|
+
|
79
|
+
h4. Campaign Finder Methods
|
80
|
+
|
81
|
+
There are finder methods for campaigns as well. Refer to _Hominid::Campaign_ to see the other finders available.
|
82
|
+
|
83
|
+
<pre><code>campaigns = Hominid::Campaign.all</code></pre>
|
84
|
+
|
85
|
+
<pre><code>campaigns = Hominid::Campaign.find_by_list_name("List Name")</code></pre>
|
86
|
+
|
87
|
+
h4. Creating a Campaign
|
88
|
+
|
89
|
+
You can create new campaigns using Hominid as well. Please refer to the documentation in _Hominid::Base_ for more information about the options available when creating a new campaign.
|
90
|
+
|
91
|
+
<pre><code>new_campaign = Hominid::Campaign.create('regular', options, content, segment_opts, type_opts)</code></pre>
|
92
|
+
|
93
|
+
h4. Schedule a Campaign
|
94
|
+
|
95
|
+
As an example of how to work with a particular campaign, use the _Hominid::Campaign_ class. Extending from the previous example, since the _#create_campaign_ method returns the ID of the created campaign, we can use it to instantiate the _Hominid::Campaign_ class and schedule our new campaign to go be delivered 2 days from now:
|
96
|
+
|
97
|
+
<pre><code>campaign = Hominid::Campaign.new(:id => new_campaign)</code></pre>
|
98
|
+
|
99
|
+
<pre><code>campaign.schedule_campaign(2.days.from_now)</code></pre>
|
100
|
+
|
101
|
+
h3. Helper Methods
|
102
|
+
|
103
|
+
The _Hominid::Helper_ class provides a way to access the helper methods for the Mailchimp API. For example, to create a new folder for filing campaigns:
|
104
|
+
|
105
|
+
<pre><code>folder = Hominid::Helper.create_folder("Folder Name")</code></pre>
|
106
|
+
|
107
|
+
h2. Syncing Your Application
|
108
|
+
|
109
|
+
If you are integrating an application with Mailchimp, Hominid will provide a way for your app to connect with your Mailchimp account. However, it does not provide a way for Mailchimp to connect to your application, which is why Mailchimp has implemented "web hooks":http://www.mailchimp.com/api/webhooks/.
|
110
|
+
|
111
|
+
The _Hominid::Webhook_ class helps with receiving <tt>POST</tt> data from a Mailchimp webhook:
|
112
|
+
|
113
|
+
<pre><code>hook = Hominid::Webhook.new(params)
|
114
|
+
case hook.event
|
115
|
+
when "subscribe"
|
116
|
+
user = User.find_by_email(hook.email)
|
117
|
+
user.opted_in = true
|
118
|
+
user.save
|
119
|
+
when "unsubscribe"
|
120
|
+
user = User.find_by_email(hook.email)
|
121
|
+
user.opted_in = false
|
122
|
+
user.save
|
123
|
+
when "profile"
|
124
|
+
user = User.find_by_email(hook.email)
|
125
|
+
user.first_name = hook.first_name
|
126
|
+
user.last_name = hook.last_name
|
127
|
+
user.email_type = hook.email_type
|
128
|
+
user.save
|
129
|
+
when "upemail"
|
130
|
+
user = User.find_by_email(hook.old_email)
|
131
|
+
user.email = hook.new_email
|
132
|
+
user.save
|
133
|
+
end</code></pre>
|
134
|
+
|
135
|
+
h2. Contributors
|
136
|
+
|
137
|
+
Hominid is maintained by "Brian Getting":http://terra-firma-design.com. A very special thank-you to "Michael Strüder":http://github.com/mikezter for all of his hard work. Also, Hominid wouldn't be anywhere near as awesome as it is today without fantastic contributions and inspiration from:
|
138
|
+
|
139
|
+
* "Alan Harper":http://github.com/aussiegeek
|
140
|
+
* "Will":http://github.com/willinfront
|
141
|
+
* "Ben Woosley":http://github.com/Empact
|
142
|
+
* "banker":http://github.com/banker
|
143
|
+
* "Kristoffer Renholm":http://github.com/renholm
|
144
|
+
* "Wiktor Schmidt":http://github.com/netguru
|
145
|
+
* "ron":http://github.com/ron
|
146
|
+
* "Matthew Carlson":http://mandarinsoda.com/
|
147
|
+
* "Kelly Mahan":http://digimedia.com/
|
148
|
+
* "C.G. Brown":http://www.projectlocker.com/
|
149
|
+
|
150
|
+
h2. Note on Patches/Pull Requests
|
151
|
+
|
152
|
+
# Fork the project.
|
153
|
+
# Make your feature addition or bug fix.
|
154
|
+
# Add tests for it. This is important so I don't break it in a future version unintentionally.
|
155
|
+
# Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
156
|
+
# Send me a pull request. Bonus points for topic branches.
|
157
|
+
|
158
|
+
h2. Copyright
|
159
|
+
|
160
|
+
Copyright (c) 2009 Brian Getting. See LICENSE for details.
|
161
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "babney-hominid"
|
8
|
+
gem.summary = %Q{Hominid is a Ruby gem for interacting with the Mailchimp API.}
|
9
|
+
gem.description = %Q{Hominid is a Ruby gem that provides a wrapper for interacting with the Mailchimp email marketing service API.}
|
10
|
+
gem.email = "brian@terra-firma-design.com"
|
11
|
+
gem.homepage = "http://github.com/bgetting/hominid"
|
12
|
+
gem.authors = ["Brian Getting", "Michael Strüder"]
|
13
|
+
gem.add_development_dependency "shoulda"
|
14
|
+
end
|
15
|
+
Jeweler::GemcutterTasks.new
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'rake/testtask'
|
21
|
+
Rake::TestTask.new(:test) do |test|
|
22
|
+
test.libs << 'lib' << 'test'
|
23
|
+
test.pattern = 'test/**/*_test.rb'
|
24
|
+
test.verbose = true
|
25
|
+
end
|
26
|
+
|
27
|
+
begin
|
28
|
+
require 'rcov/rcovtask'
|
29
|
+
Rcov::RcovTask.new do |test|
|
30
|
+
test.libs << 'test'
|
31
|
+
test.pattern = 'test/**/*_test.rb'
|
32
|
+
test.verbose = true
|
33
|
+
end
|
34
|
+
rescue LoadError
|
35
|
+
task :rcov do
|
36
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
task :test => :check_dependencies
|
41
|
+
|
42
|
+
task :default => :test
|
43
|
+
|
44
|
+
require 'rake/rdoctask'
|
45
|
+
Rake::RDocTask.new do |rdoc|
|
46
|
+
if File.exist?('VERSION')
|
47
|
+
version = File.read('VERSION')
|
48
|
+
else
|
49
|
+
version = ""
|
50
|
+
end
|
51
|
+
|
52
|
+
rdoc.rdoc_dir = 'rdoc'
|
53
|
+
rdoc.title = "hominid #{version}"
|
54
|
+
rdoc.rdoc_files.include('README*')
|
55
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
56
|
+
end
|
57
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.0.1
|
data/hominid.gemspec
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{hominid}
|
8
|
+
s.version = "2.0.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Brian Getting", "Michael Str\303\274der"]
|
12
|
+
s.date = %q{2009-11-11}
|
13
|
+
s.description = %q{Hominid is a Ruby gem that provides a wrapper for interacting with the Mailchimp email marketing service API.}
|
14
|
+
s.email = %q{brian@terra-firma-design.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.textile"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".gitignore",
|
21
|
+
"LICENSE",
|
22
|
+
"README.textile",
|
23
|
+
"Rakefile",
|
24
|
+
"VERSION",
|
25
|
+
"hominid.gemspec",
|
26
|
+
"hominid.yml.tpl",
|
27
|
+
"lib/hominid.rb",
|
28
|
+
"lib/hominid/base.rb",
|
29
|
+
"lib/hominid/campaign.rb",
|
30
|
+
"lib/hominid/helper.rb",
|
31
|
+
"lib/hominid/list.rb",
|
32
|
+
"lib/hominid/webhook.rb",
|
33
|
+
"tasks/rails/hominid.rake",
|
34
|
+
"test/hominid_test.rb",
|
35
|
+
"test/test_helper.rb"
|
36
|
+
]
|
37
|
+
s.homepage = %q{http://github.com/bgetting/hominid}
|
38
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
39
|
+
s.require_paths = ["lib"]
|
40
|
+
s.rubygems_version = %q{1.3.5}
|
41
|
+
s.summary = %q{Hominid is a Ruby gem for interacting with the Mailchimp API.}
|
42
|
+
s.test_files = [
|
43
|
+
"test/hominid_test.rb",
|
44
|
+
"test/test_helper.rb"
|
45
|
+
]
|
46
|
+
|
47
|
+
if s.respond_to? :specification_version then
|
48
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
49
|
+
s.specification_version = 3
|
50
|
+
|
51
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
52
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
53
|
+
else
|
54
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
55
|
+
end
|
56
|
+
else
|
57
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
data/hominid.yml.tpl
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# Get your API key at http://admin.mailchimp.com/account/api/
|
2
|
+
|
3
|
+
development:
|
4
|
+
username:
|
5
|
+
password:
|
6
|
+
api_key:
|
7
|
+
send_goodbye: false
|
8
|
+
send_notify: false
|
9
|
+
double_opt_in: false
|
10
|
+
|
11
|
+
test:
|
12
|
+
username:
|
13
|
+
password:
|
14
|
+
api_key:
|
15
|
+
send_goodbye: false
|
16
|
+
send_notify: false
|
17
|
+
double_opt_in: false
|
18
|
+
|
19
|
+
production:
|
20
|
+
username:
|
21
|
+
password:
|
22
|
+
api_key:
|
23
|
+
send_goodbye: false
|
24
|
+
send_notify: false
|
25
|
+
double_opt_in: false
|
data/lib/hominid.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'xmlrpc/client'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
module Hominid
|
5
|
+
|
6
|
+
class StandardError < ::StandardError
|
7
|
+
end
|
8
|
+
|
9
|
+
class APIError < StandardError
|
10
|
+
def initialize(error)
|
11
|
+
super("<#{error.faultCode}> #{error.message}")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class ListError < APIError
|
16
|
+
end
|
17
|
+
|
18
|
+
class ListEmailError < ListError
|
19
|
+
end
|
20
|
+
|
21
|
+
class ListMergeError < ListError
|
22
|
+
end
|
23
|
+
|
24
|
+
class AlreadySubscribed < ListEmailError
|
25
|
+
end
|
26
|
+
|
27
|
+
class AlreadyUnsubscribed < ListEmailError
|
28
|
+
end
|
29
|
+
|
30
|
+
class NotExists < ListEmailError
|
31
|
+
end
|
32
|
+
|
33
|
+
class NotSubscribed < ListEmailError
|
34
|
+
end
|
35
|
+
|
36
|
+
class CommunicationError < StandardError
|
37
|
+
def initialize(message)
|
38
|
+
super(message)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
begin
|
44
|
+
# include the provided rake task
|
45
|
+
require 'rake'
|
46
|
+
unless Rake::Task.task_defined? "hominid:config"
|
47
|
+
load File.join(File.dirname(__FILE__), '..', 'tasks', 'rails', 'hominid.rake')
|
48
|
+
end
|
49
|
+
rescue LoadError
|
50
|
+
# silently skip rake task inclusion unless the rake gem is installed
|
51
|
+
end
|
52
|
+
|
53
|
+
require 'hominid/base'
|
54
|
+
|
data/lib/hominid/base.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
module Hominid
|
2
|
+
class Base
|
3
|
+
|
4
|
+
# MailChimp API Documentation: http://www.mailchimp.com/api/1.2/
|
5
|
+
MAILCHIMP_API_VERSION = "1.2"
|
6
|
+
|
7
|
+
def initialize(config = {})
|
8
|
+
if defined?(Rails.root) && (!config || config.empty?)
|
9
|
+
config = YAML.load(File.open("#{Rails.root}/config/hominid.yml"))[Rails.env].symbolize_keys
|
10
|
+
end
|
11
|
+
api_endpoint = config[:api_key].split('-').last
|
12
|
+
config.merge(:username => config[:username].to_s, :password => config[:password].to_s)
|
13
|
+
defaults = {:send_welcome => false,
|
14
|
+
:double_opt_in => false,
|
15
|
+
:update_existing => true,
|
16
|
+
:replace_interests => true,
|
17
|
+
:merge_tags => {},
|
18
|
+
:secure => false}
|
19
|
+
@config = defaults.merge(config).freeze
|
20
|
+
if config[:secure]
|
21
|
+
@chimpApi = XMLRPC::Client.new2("https://#{api_endpoint}.api.mailchimp.com/#{MAILCHIMP_API_VERSION}/")
|
22
|
+
else
|
23
|
+
@chimpApi = XMLRPC::Client.new2("http://#{api_endpoint}.api.mailchimp.com/#{MAILCHIMP_API_VERSION}/")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Security related methods
|
28
|
+
# --------------------------------
|
29
|
+
|
30
|
+
def add_api_key
|
31
|
+
@chimpApi.call("apikeyAdd", *@config.values_at(:username, :password, :api_key))
|
32
|
+
end
|
33
|
+
|
34
|
+
def expire_api_key
|
35
|
+
@chimpApi.call("apikeyExpire", *@config.values_at(:username, :password, :api_key))
|
36
|
+
end
|
37
|
+
|
38
|
+
def api_keys(include_expired = false)
|
39
|
+
username, password = *@config.values_at(:username, :password)
|
40
|
+
@chimpApi.call("apikeys", username, password, include_expired)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Used internally by Hominid
|
44
|
+
# --------------------------------
|
45
|
+
|
46
|
+
# handle common cases for which the Mailchimp API would raise Exceptions
|
47
|
+
def clean_merge_tags(merge_tags)
|
48
|
+
return {} unless merge_tags.is_a? Hash
|
49
|
+
merge_tags.each do |key, value|
|
50
|
+
if merge_tags[key].is_a? String
|
51
|
+
merge_tags[key] = value.gsub("\v", '')
|
52
|
+
elsif merge_tags[key].nil?
|
53
|
+
merge_tags[key] = ''
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def apply_defaults_to(options)
|
59
|
+
@config.merge(options)
|
60
|
+
end
|
61
|
+
|
62
|
+
def call(method, *args)
|
63
|
+
@chimpApi.call(method, @config[:api_key], *args)
|
64
|
+
rescue XMLRPC::FaultException => error
|
65
|
+
case error.faultCode
|
66
|
+
when 230
|
67
|
+
raise AlreadySubscribed.new(error)
|
68
|
+
when 231
|
69
|
+
raise AlreadyUnsubscribed.new(error)
|
70
|
+
when 232
|
71
|
+
raise NotExists.new(error)
|
72
|
+
when 233, 215
|
73
|
+
raise NotSubscribed.new(error)
|
74
|
+
else
|
75
|
+
raise APIError.new(error)
|
76
|
+
end
|
77
|
+
rescue RuntimeError => error
|
78
|
+
if error.message =~ /Wrong type NilClass\. Not allowed!/
|
79
|
+
hashes = args.select{|a| a.is_a? Hash}
|
80
|
+
errors = hashes.select{|k, v| v.nil? }.collect{ |k, v| "#{k} is Nil." }.join(' ')
|
81
|
+
raise CommunicationError.new(errors)
|
82
|
+
else
|
83
|
+
raise error
|
84
|
+
end
|
85
|
+
rescue Exception => error
|
86
|
+
raise CommunicationError.new(error.message)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
@@ -0,0 +1,172 @@
|
|
1
|
+
module Hominid
|
2
|
+
|
3
|
+
class Campaign < Base
|
4
|
+
|
5
|
+
# Campaign related methods
|
6
|
+
# --------------------------------
|
7
|
+
|
8
|
+
attr_reader :campaign_id
|
9
|
+
attr_reader :attributes
|
10
|
+
|
11
|
+
def initialize(*args)
|
12
|
+
options = args.last.is_a?(Hash) ? args.last : {}
|
13
|
+
raise StandardError.new('Please provide a Campaign ID.') unless options[:id]
|
14
|
+
@campaign_id = options.delete(:id)
|
15
|
+
@attributes = options.delete(:attributes)
|
16
|
+
super(options)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.all
|
20
|
+
# Get all campaigns for this mailchimp account
|
21
|
+
new(:id => 0).call("campaigns").to_a.collect { |c| Campaign.new(:id => c.delete('id'), :attributes => c) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.find_by_list_name(list_name)
|
25
|
+
new(:id => 0).call("campaigns", {:list_id => List.find_by_name(list_name).list_id}).to_a.collect { |c| Campaign.new(:id=> c.delete('id'), :attributes => c) }
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.find_by_list_id(list_id)
|
29
|
+
# Find all campaigns for the given list
|
30
|
+
new(:id => 0).call("campaigns", {:list_id => list_id}).to_a.collect { |c| Campaign.new(:id=> c.delete('id'), :attributes => c) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.find_by_title(title)
|
34
|
+
# Find campaign by title
|
35
|
+
all.find { |c| c.attributes['title'] =~ /#{title}/ }
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.find_by_type(type)
|
39
|
+
# Find campaign by type. Possible choices are:
|
40
|
+
# 'regular'
|
41
|
+
# 'plaintext'
|
42
|
+
# 'absplit'
|
43
|
+
# 'rss'
|
44
|
+
# 'inspection'
|
45
|
+
# 'trans'
|
46
|
+
# 'auto'
|
47
|
+
all.find { |campaign| campaign.attributes['type'] =~ /#{type}/ }
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.find_by_web_id(web_id)
|
51
|
+
# Find campaigns by web_id
|
52
|
+
all.find { |campaign| campaign.attributes['web_id'] == web_id.to_i }
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.find_by_id(id)
|
56
|
+
# Find campaign by id
|
57
|
+
all.find { |campaign| (campaign.campaign_id == id.to_s) }
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.find(id_or_web_id)
|
61
|
+
# Campaign finder method
|
62
|
+
all = self.all
|
63
|
+
campaign = self.find_by_id(id_or_web_id.to_s).to_a + self.find_by_web_id(id_or_web_id.to_i).to_a
|
64
|
+
return campaign.blank? ? nil : campaign.first
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.create(type = 'regular', options = {}, content = {}, segment_options = {}, type_opts = {})
|
68
|
+
# Create a new campaign
|
69
|
+
# The options hash should be structured as follows:
|
70
|
+
#
|
71
|
+
# :list_id = (string) The ID of the list to send this campaign to.
|
72
|
+
# :subject = (string) The subject of the campaign.
|
73
|
+
# :from_email = (string) The email address this campaign will come from.
|
74
|
+
# :from_name = (string) The name that this campaign will come from.
|
75
|
+
# :to_email = (string) The To: name recipients will see.
|
76
|
+
# :template_id = (integer) The ID of the template to use for this campaign (optional).
|
77
|
+
# :folder_id = (integer) The ID of the folder to file this campaign in (optional).
|
78
|
+
# :tracking = (array) What to track for this campaign (optional).
|
79
|
+
# :title = (string) Internal title for this campaign (optional).
|
80
|
+
# :authenticate = (boolean) Set to true to authenticate campaign (optional).
|
81
|
+
# :analytics = (array) Google analytics tags (optional).
|
82
|
+
# :auto_footer = (boolean) Auto-generate the footer (optional)?
|
83
|
+
# :inline_css = (boolean) Inline the CSS styles (optional)?
|
84
|
+
# :generate_text = (boolean) Auto-generate text from HTML email (optional)?
|
85
|
+
#
|
86
|
+
# Visit http://www.mailchimp.com/api/1.2/campaigncreate.func.php for more information about creating
|
87
|
+
# campaigns via the API.
|
88
|
+
#
|
89
|
+
new(:id => 0).call("campaignCreate", type, options, content, segment_options, type_opts)
|
90
|
+
## TODO: Return the new campaign with the ID returned from the API
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.templates
|
94
|
+
# Get the templates for this account
|
95
|
+
new(:id => 0).call("campaignTemplates")
|
96
|
+
end
|
97
|
+
|
98
|
+
def add_order(order)
|
99
|
+
# Attach Ecommerce Order Information to a campaign.
|
100
|
+
# The order hash should be structured as follows:
|
101
|
+
#
|
102
|
+
# :id = (string) the order id
|
103
|
+
# :email_id = (string) email id of the subscriber (mc_eid query string)
|
104
|
+
# :total = (double) Show only campaigns with this from_name.
|
105
|
+
# :shipping = (string) *optional - the total paid for shipping fees.
|
106
|
+
# :tax = (string) *optional - the total tax paid.
|
107
|
+
# :store_id = (string) a unique id for the store sending the order in
|
108
|
+
# :store_name = (string) *optional - A readable name for the store, typicaly the hostname.
|
109
|
+
# :plugin_id = (string) the MailChimp-assigned Plugin Id. Using 1214 for the moment.
|
110
|
+
# :items = (array) the individual line items for an order, using the following keys:
|
111
|
+
#
|
112
|
+
# :line_num = (integer) *optional - line number of the item on the order
|
113
|
+
# :product_id = (integer) internal product id
|
114
|
+
# :product_name = (string) the name for the product_id associated with the item
|
115
|
+
# :category_id = (integer) internal id for the (main) category associated with product
|
116
|
+
# :category_name = (string) the category name for the category id
|
117
|
+
# :qty = (double) the quantity of items ordered
|
118
|
+
# :cost = (double) the cost of a single item (i.e., not the extended cost of the line)
|
119
|
+
order = order.merge(:campaign_id => @campaign_id)
|
120
|
+
call("campaignEcommAddOrder", order)
|
121
|
+
end
|
122
|
+
|
123
|
+
def campaign_stats()
|
124
|
+
# Get the stats of a campaign
|
125
|
+
call("campaignStats", @campaign_id)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Get the HTML & text content for a campaign
|
129
|
+
# :for_archive = (boolean) default true, true returns the content as it would appear in the archive, false returns the raw HTML/text
|
130
|
+
def campaign_content(for_archive = true)
|
131
|
+
# Get the content of a campaign
|
132
|
+
call("campaignContent", @campaign_id, for_archive)
|
133
|
+
end
|
134
|
+
|
135
|
+
def delete_campaign()
|
136
|
+
# Delete a campaign
|
137
|
+
call("campaignDelete", @campaign_id)
|
138
|
+
end
|
139
|
+
|
140
|
+
def replicate_campaign()
|
141
|
+
# Replicate a campaign (returns ID of new campaign)
|
142
|
+
call("campaignReplicate", @campaign_id)
|
143
|
+
end
|
144
|
+
|
145
|
+
def schedule_campaign(time = "#{1.day.from_now}")
|
146
|
+
# Schedule a campaign
|
147
|
+
## TODO: Add support for A/B Split scheduling
|
148
|
+
call("campaignSchedule", @campaign_id, time)
|
149
|
+
end
|
150
|
+
|
151
|
+
def send_now()
|
152
|
+
# Send a campaign
|
153
|
+
call("campaignSendNow", @campaign_id)
|
154
|
+
end
|
155
|
+
|
156
|
+
# Send a test of a campaign
|
157
|
+
def send_test(emails = {})
|
158
|
+
call("campaignSendTest", @campaign_id, emails)
|
159
|
+
end
|
160
|
+
|
161
|
+
def update(name, value)
|
162
|
+
# Update a campaign
|
163
|
+
call("campaignUpdate", @campaign_id, name, value)
|
164
|
+
end
|
165
|
+
|
166
|
+
def unschedule()
|
167
|
+
# Unschedule a campaign
|
168
|
+
call("campaignUnschedule", @campaign_id)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Hominid
|
2
|
+
|
3
|
+
class Helper < Base
|
4
|
+
|
5
|
+
# Helper methods
|
6
|
+
# --------------------------------
|
7
|
+
|
8
|
+
def self.account_details(options = {})
|
9
|
+
# Get details for this account.
|
10
|
+
new(options).call("getAccountDetails")
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.convert_css_to_inline(html, strip_css = false, options = {})
|
14
|
+
# Convert CSS styles to inline styles and (optionally) remove original styles
|
15
|
+
new.call("inlineCss", html, strip_css)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.create_folder(name, options = {})
|
19
|
+
# Create a new folder to file campaigns in
|
20
|
+
new(options).call("createFolder", name)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.generate_text(type, content, options = {})
|
24
|
+
# Have HTML content auto-converted to a text-only format.
|
25
|
+
# The options for text type are:
|
26
|
+
# 'html' => Expects a string of HTML(default).
|
27
|
+
# 'template' => Expects an array.
|
28
|
+
# 'url' => Expects a valid and public URL.
|
29
|
+
# 'cid' => Expects a campaign ID.
|
30
|
+
# 'tid' => Expects a template ID.
|
31
|
+
new(options).call("generateText", type, content)
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.html_to_text(content, options = {})
|
35
|
+
# Convert HTML content to text
|
36
|
+
new(options).call("generateText", 'html', content)
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.ping(options = {})
|
40
|
+
# Ping the Mailchimp API
|
41
|
+
new(options).call("ping")
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
data/lib/hominid/list.rb
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
module Hominid
|
2
|
+
|
3
|
+
class List < Base
|
4
|
+
|
5
|
+
# List related methods
|
6
|
+
# --------------------------------
|
7
|
+
|
8
|
+
attr_reader :list_id
|
9
|
+
attr_reader :attributes
|
10
|
+
|
11
|
+
def initialize(*args)
|
12
|
+
options = args.last.is_a?(Hash) ? args.last : {}
|
13
|
+
raise StandardError.new('Please provide a List ID.') unless options[:id]
|
14
|
+
@list_id = options.delete(:id)
|
15
|
+
@attributes = options.delete(:attributes)
|
16
|
+
super(options)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.all
|
20
|
+
# Get all lists for this mailchimp account
|
21
|
+
new(:id => 0).call("lists").to_a.collect { |list| List.new(:id => list.delete('id'), :attributes => list) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.find_by_name(name)
|
25
|
+
# Find list by name
|
26
|
+
all.find { |list| list.attributes['name'] =~ /#{name}/ }
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.find_by_web_id(web_id)
|
30
|
+
# Find list by name
|
31
|
+
all.find { |list| (list.attributes['web_id'] == web_id.to_i) }
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.find_by_id(id)
|
35
|
+
# Find list by id
|
36
|
+
all.find { |list| (list.list_id == id.to_s) }
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.find(id_or_web_id)
|
40
|
+
# List finder method
|
41
|
+
all = self.all
|
42
|
+
list = self.find_by_id(id_or_web_id.to_s).to_a + self.find_by_web_id(id_or_web_id.to_i).to_a
|
43
|
+
return list.blank? ? nil : list.first
|
44
|
+
end
|
45
|
+
|
46
|
+
def create_group(group)
|
47
|
+
# Add an interest group to a list
|
48
|
+
call("listInterestGroupAdd", @list_id, group)
|
49
|
+
end
|
50
|
+
alias :interest_group_add :create_group
|
51
|
+
|
52
|
+
def create_tag(tag, name, required = false)
|
53
|
+
# Add a merge tag to a list
|
54
|
+
call("listMergeVarAdd", @list_id, tag, name, required)
|
55
|
+
end
|
56
|
+
alias :merge_var_add :create_tag
|
57
|
+
|
58
|
+
def delete_group(group)
|
59
|
+
# Delete an interest group for a list
|
60
|
+
call("listInterestGroupDel", @list_id, group)
|
61
|
+
end
|
62
|
+
alias :interest_group_del :delete_group
|
63
|
+
|
64
|
+
def delete_tag(tag)
|
65
|
+
# Delete a merge tag and all its members
|
66
|
+
call("listMergeVarDel", @list_id, tag)
|
67
|
+
end
|
68
|
+
alias :merge_var_del :delete_tag
|
69
|
+
|
70
|
+
def groups()
|
71
|
+
# Get the interest groups for a list
|
72
|
+
call("listInterestGroups", @list_id)
|
73
|
+
end
|
74
|
+
alias :interest_groups :groups
|
75
|
+
|
76
|
+
|
77
|
+
def member_info(email)
|
78
|
+
# Get a member of a list
|
79
|
+
call("listMemberInfo", @list_id, email)
|
80
|
+
end
|
81
|
+
|
82
|
+
def members(status = "subscribed", since = "2000-01-01 00:00:00", start = 0, limit = 100)
|
83
|
+
# Get members of a list based on status
|
84
|
+
# Select members based on one of the following statuses:
|
85
|
+
# 'subscribed'
|
86
|
+
# 'unsubscribed'
|
87
|
+
# 'cleaned'
|
88
|
+
# 'updated'
|
89
|
+
#
|
90
|
+
# Select members that have updated their status or profile by providing
|
91
|
+
# a "since" date in the format of YYYY-MM-DD HH:MM:SS
|
92
|
+
call("listMembers", @list_id, status, since, start, limit)
|
93
|
+
end
|
94
|
+
|
95
|
+
def merge_tags()
|
96
|
+
# Get the merge tags for a list
|
97
|
+
call("listMergeVars", @list_id)
|
98
|
+
end
|
99
|
+
alias :merge_vars :merge_tags
|
100
|
+
|
101
|
+
def subscribe(email, options = {})
|
102
|
+
# Subscribe a member to this list
|
103
|
+
merge_tags = clean_merge_tags options[:merge_tags]
|
104
|
+
options = apply_defaults_to({:email_type => "html"}.merge(options))
|
105
|
+
call(
|
106
|
+
"listSubscribe",
|
107
|
+
@list_id,
|
108
|
+
email,
|
109
|
+
merge_tags,
|
110
|
+
*options.values_at(
|
111
|
+
:email_type,
|
112
|
+
:double_opt_in,
|
113
|
+
:update_existing,
|
114
|
+
:replace_interests,
|
115
|
+
:send_welcome
|
116
|
+
)
|
117
|
+
)
|
118
|
+
end
|
119
|
+
|
120
|
+
def subscribe_many(subscribers, options = {})
|
121
|
+
# Subscribe an array of email addresses
|
122
|
+
# subscribers(array) = [{:EMAIL => 'example@email.com', :EMAIL_TYPE => 'html'}]
|
123
|
+
subscribers = subscribers.collect { |subscriber| clean_merge_tags(subscriber) }
|
124
|
+
options = apply_defaults_to({:update_existing => true}.merge(options))
|
125
|
+
call("listBatchSubscribe", @list_id, subscribers, *options.values_at(:double_opt_in, :update_existing, :replace_interests))
|
126
|
+
end
|
127
|
+
alias :batch_subscribe :subscribe_many
|
128
|
+
|
129
|
+
def unsubscribe(current_email, options = {})
|
130
|
+
# Unsubscribe a list member
|
131
|
+
options = apply_defaults_to({:delete_member => true}.merge(options))
|
132
|
+
call("listUnsubscribe", @list_id, current_email, *options.values_at(:delete_member, :send_goodbye, :send_notify))
|
133
|
+
end
|
134
|
+
|
135
|
+
def unsubscribe_many(emails, options = {})
|
136
|
+
# Unsubscribe an array of email addresses
|
137
|
+
# emails(array) = ['first@email.com', 'second@email.com']
|
138
|
+
options = apply_defaults_to({:delete_member => true}.merge(options))
|
139
|
+
call("listBatchUnsubscribe", @list_id, emails, *options.values_at(:delete_member, :send_goodbye, :send_notify))
|
140
|
+
end
|
141
|
+
alias :batch_unsubscribe :unsubscribe_many
|
142
|
+
|
143
|
+
def update_member(current_email, merge_tags = {}, email_type = "html", replace_interests = true)
|
144
|
+
# Update a member of this list
|
145
|
+
call("listUpdateMember", @list_id, current_email, merge_tags, email_type, replace_interests)
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
@@ -0,0 +1,131 @@
|
|
1
|
+
module Hominid
|
2
|
+
|
3
|
+
class Webhook < Base
|
4
|
+
# Expects a hash of POST data generated from Mailchimp:
|
5
|
+
#
|
6
|
+
# "type": "unsubscribe",
|
7
|
+
# "fired_at": "2009-03-26 21:54:00",
|
8
|
+
# "data[email]": "sample@emailaddress.com"
|
9
|
+
#
|
10
|
+
# Simple Usage:
|
11
|
+
#
|
12
|
+
# h = Hominid::Webhook.new(params)
|
13
|
+
#
|
14
|
+
# Sample params from Mailchimp webhook:
|
15
|
+
# params => { "type" => "subscribe",
|
16
|
+
# "fired_at" => "2009-03-26 21:35:57",
|
17
|
+
# "data" => { "id" => "8a25ff1d98",
|
18
|
+
# "list_id" => "8a25ff1d98",
|
19
|
+
# "email" => "api@mailchimp.com",
|
20
|
+
# "email_type" => "html",
|
21
|
+
# "merges" => {"EMAIL" => "api@mailchimp.com",
|
22
|
+
# "FNAME" => "Brian",
|
23
|
+
# "LNAME" => "Getting",
|
24
|
+
# "INTERESTS" => "Group1,Group2"},
|
25
|
+
# "ip_opt" => "10.20.10.30",
|
26
|
+
# "ip_signup" => "10.20.10.30" }}
|
27
|
+
#
|
28
|
+
# Returns an object with the following methods (NOTE: Not all methods are available
|
29
|
+
# for all event types. Refer to http://www.mailchimp.com/api/webhooks/ for information
|
30
|
+
# on what data will be available for each event):
|
31
|
+
#
|
32
|
+
# h.event <= (String) The event that fired the request. Possible events are:
|
33
|
+
# "subscribe", "unsubscribe", "profile", "upemail", "cleaned"
|
34
|
+
# h.fired_at <= (Datetime) When the webhook request was fired.
|
35
|
+
# h.id <= (String) The ID of the webhook request.
|
36
|
+
# h.list_id <= (String) The ID of the list that generated the request.
|
37
|
+
# h.email <= (String) The email address of the subscriber that generated the request.
|
38
|
+
# h.email_type <= (String) The email type of the subscriber that generated the request.
|
39
|
+
# h.first_name <= (String) The first name of the subscriber (if available).
|
40
|
+
# h.last_name <= (String) The first name of the subscriber (if available).
|
41
|
+
# h.interests <= (Array) An array of the interest groups.
|
42
|
+
# h.ip_opt <= (String) The opt in IP address.
|
43
|
+
# h.ip_signup <= (String) The signup IP address.
|
44
|
+
#
|
45
|
+
|
46
|
+
attr_reader :request
|
47
|
+
|
48
|
+
def initialize(*args)
|
49
|
+
post_data = args.last
|
50
|
+
raise HominidError.new('Please provide the POST data from a Mailchimp webhook request.') unless post_data.is_a?(Hash)
|
51
|
+
post_data.merge!({"event" => "#{post_data.delete('type')}"})
|
52
|
+
@request = hash_to_object(post_data)
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
def email
|
57
|
+
self.request.data.email if self.request.data.email
|
58
|
+
end
|
59
|
+
|
60
|
+
def email_type
|
61
|
+
self.request.data.email_type if self.request.data.email_type
|
62
|
+
end
|
63
|
+
|
64
|
+
def event
|
65
|
+
self.request.event if self.request.event
|
66
|
+
end
|
67
|
+
|
68
|
+
def fired_at
|
69
|
+
self.request.fired_at.to_datetime if self.request.fired_at
|
70
|
+
end
|
71
|
+
|
72
|
+
def first_name
|
73
|
+
self.request.data.merges.fname if self.request.data.merges.fname
|
74
|
+
end
|
75
|
+
|
76
|
+
def last_name
|
77
|
+
self.request.data.merges.lname if self.request.data.merges.lname
|
78
|
+
end
|
79
|
+
|
80
|
+
def id
|
81
|
+
self.request.data.id if self.request.data.id
|
82
|
+
end
|
83
|
+
|
84
|
+
def interests
|
85
|
+
self.request.data.merges.interests.split(',') if self.request.data.merges.interests
|
86
|
+
end
|
87
|
+
|
88
|
+
def ip_opt
|
89
|
+
self.request.data.ip_opt if self.request.data.ip_opt
|
90
|
+
end
|
91
|
+
|
92
|
+
def ip_signup
|
93
|
+
self.request.data.ip_signup if self.request.data.ip_signup
|
94
|
+
end
|
95
|
+
|
96
|
+
def list_id
|
97
|
+
self.request.data.list_id if self.request.data.list_id
|
98
|
+
end
|
99
|
+
|
100
|
+
def new_email
|
101
|
+
self.request.data.new_email if self.request.data.new_email
|
102
|
+
end
|
103
|
+
|
104
|
+
def old_email
|
105
|
+
self.request.data.old_email if self.request.data.old_email
|
106
|
+
end
|
107
|
+
|
108
|
+
def reason
|
109
|
+
self.request.data.reason if self.request.data.reason
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def hash_to_object(object)
|
115
|
+
return case object
|
116
|
+
when Hash
|
117
|
+
object = object.clone
|
118
|
+
object.each do |key, value|
|
119
|
+
object[key.downcase] = hash_to_object(value)
|
120
|
+
end
|
121
|
+
OpenStruct.new(object)
|
122
|
+
when Array
|
123
|
+
object = object.clone
|
124
|
+
object.map! { |i| hash_to_object(i) }
|
125
|
+
else
|
126
|
+
object
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rake'
|
2
|
+
namespace :hominid do
|
3
|
+
# Task to create the config file
|
4
|
+
desc "Generate a Hominid config file"
|
5
|
+
task :config => :environment do |t|
|
6
|
+
require 'fileutils'
|
7
|
+
if defined?(Rails.root)
|
8
|
+
config_file = File.join(Rails.root, 'config', 'hominid.yml')
|
9
|
+
template_file = File.join(File.dirname(__FILE__), '..', '..', 'hominid.yml.tpl')
|
10
|
+
unless File.exists? config_file
|
11
|
+
FileUtils.cp(
|
12
|
+
File.join(File.dirname(__FILE__), '..', '..', 'hominid.yml.tpl'),
|
13
|
+
File.join(Rails.root, 'config', 'hominid.yml')
|
14
|
+
)
|
15
|
+
puts 'Please edit config/hominid.yml to your needs.'
|
16
|
+
else
|
17
|
+
puts 'We left your existing config/hominid.yml untouched.'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: babney-hominid
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Brian Getting
|
8
|
+
- "Michael Str\xC3\xBCder"
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2009-11-18 00:00:00 -08:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: shoulda
|
18
|
+
type: :development
|
19
|
+
version_requirement:
|
20
|
+
version_requirements: !ruby/object:Gem::Requirement
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: "0"
|
25
|
+
version:
|
26
|
+
description: Hominid is a Ruby gem that provides a wrapper for interacting with the Mailchimp email marketing service API.
|
27
|
+
email: brian@terra-firma-design.com
|
28
|
+
executables: []
|
29
|
+
|
30
|
+
extensions: []
|
31
|
+
|
32
|
+
extra_rdoc_files:
|
33
|
+
- LICENSE
|
34
|
+
- README.textile
|
35
|
+
files:
|
36
|
+
- .gitignore
|
37
|
+
- LICENSE
|
38
|
+
- README.textile
|
39
|
+
- Rakefile
|
40
|
+
- VERSION
|
41
|
+
- hominid.gemspec
|
42
|
+
- hominid.yml.tpl
|
43
|
+
- lib/hominid.rb
|
44
|
+
- lib/hominid/base.rb
|
45
|
+
- lib/hominid/campaign.rb
|
46
|
+
- lib/hominid/helper.rb
|
47
|
+
- lib/hominid/list.rb
|
48
|
+
- lib/hominid/webhook.rb
|
49
|
+
- tasks/rails/hominid.rake
|
50
|
+
- test/hominid_test.rb
|
51
|
+
- test/test_helper.rb
|
52
|
+
has_rdoc: true
|
53
|
+
homepage: http://github.com/bgetting/hominid
|
54
|
+
licenses: []
|
55
|
+
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options:
|
58
|
+
- --charset=UTF-8
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: "0"
|
66
|
+
version:
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: "0"
|
72
|
+
version:
|
73
|
+
requirements: []
|
74
|
+
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 1.3.5
|
77
|
+
signing_key:
|
78
|
+
specification_version: 3
|
79
|
+
summary: Hominid is a Ruby gem for interacting with the Mailchimp API.
|
80
|
+
test_files:
|
81
|
+
- test/hominid_test.rb
|
82
|
+
- test/test_helper.rb
|