chimpactions 0.0.0 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +14 -2
- data/MIT-LICENSE +20 -0
- data/README.textile +134 -0
- data/Rakefile +44 -0
- data/app/controllers/chimpactions_controller.rb +123 -0
- data/app/models/chimpaction.rb +20 -0
- data/app/views/chimpactions/_errors.html.erb +10 -0
- data/app/views/chimpactions/_form.html.erb +26 -0
- data/app/views/chimpactions/_list.html.erb +6 -0
- data/app/views/chimpactions/edit.html.erb +4 -0
- data/app/views/chimpactions/index.html.erb +22 -0
- data/app/views/chimpactions/new.html.erb +4 -0
- data/app/views/chimpactions/webhooks.html.erb +26 -0
- data/chimpactions.gemspec +9 -4
- data/config/deploy/templates/nginx.conf.tpl_ +0 -0
- data/config/deploy/templates/unicorn.conf.tpl_ +0 -0
- data/config/routes.rb +8 -0
- data/lib/chimpactions.rb +210 -2
- data/lib/chimpactions/action.rb +73 -0
- data/lib/chimpactions/engine.rb +21 -0
- data/lib/chimpactions/exception.rb +14 -0
- data/lib/chimpactions/list.rb +113 -0
- data/lib/chimpactions/notifier.rb +9 -0
- data/lib/chimpactions/setup.rb +42 -0
- data/lib/chimpactions/subscriber.rb +125 -0
- data/lib/chimpactions/utility.rb +13 -0
- data/lib/chimpactions/version.rb +1 -1
- data/lib/generators/chimpactions/customize/customize_generator.rb +19 -0
- data/lib/generators/chimpactions/customize/templates/views/_errors.html.erb +10 -0
- data/lib/generators/chimpactions/customize/templates/views/_form.html.erb +26 -0
- data/lib/generators/chimpactions/customize/templates/views/_list.html.erb +6 -0
- data/lib/generators/chimpactions/customize/templates/views/edit.html.erb +4 -0
- data/lib/generators/chimpactions/customize/templates/views/index.html.erb +22 -0
- data/lib/generators/chimpactions/customize/templates/views/new.html.erb +4 -0
- data/lib/generators/chimpactions/customize/templates/views/webhooks.html.erb +26 -0
- data/lib/generators/chimpactions/install/install_generator.rb +19 -0
- data/lib/generators/chimpactions/install/templates/README +10 -0
- data/lib/generators/chimpactions/install/templates/chimpactions.yml +39 -0
- data/lib/generators/chimpactions/install/templates/chimpactions_initializer.rb +1 -0
- data/lib/generators/chimpactions/migration/migration_generator.rb +26 -0
- data/lib/generators/chimpactions/migration/templates/create_chimpactions.rb +16 -0
- data/lib/railtie.rb +16 -0
- metadata +82 -38
- data/.gitignore +0 -4
data/Gemfile
CHANGED
@@ -1,4 +1,16 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
gem "rails", "3.0.7"
|
4
|
+
gem "capybara", ">= 0.4.0"
|
5
|
+
gem "sqlite3"
|
6
|
+
gem "gibbon", ">= 0.1.5"
|
7
|
+
# To use debugger (ruby-debug for Ruby 1.8.7+, ruby-debug19 for Ruby 1.9.2+)
|
8
|
+
# gem 'ruby-debug'
|
9
|
+
# gem 'ruby-debug19'
|
10
|
+
|
11
|
+
group :test do
|
12
|
+
gem "factory_girl"
|
13
|
+
gem "shoulda"
|
14
|
+
gem 'simplecov'
|
15
|
+
gem 'mocha'
|
16
|
+
end
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2011 Peter Bonnell / CIRCUIT LLC
|
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,134 @@
|
|
1
|
+
h1. Chimpactions
|
2
|
+
|
3
|
+
Easily move contacts between MailChimp lists in your Rails 3 application.
|
4
|
+
|
5
|
+
h2. Requirements
|
6
|
+
|
7
|
+
A MailChimp account and "API key":http://admin.mailchimp.com/account/api.
|
8
|
+
|
9
|
+
h2. Installation
|
10
|
+
|
11
|
+
h3. Base
|
12
|
+
|
13
|
+
# *_Gemfile_* -> <code>gem "chimpactions", "~> 0.0.1"</code>
|
14
|
+
# <code>rails generate chimpactions:install</code>
|
15
|
+
# _Edit config/chimpactions.yml_ with your information.
|
16
|
+
# add <code>include Chimpactions::Subscriber</code> to your model.
|
17
|
+
# add <code>after_save :chimpactions </code> (if that's what you want) to your model.
|
18
|
+
|
19
|
+
The YourModel.chimpactions method fires the actions to move subscribers as specified.
|
20
|
+
|
21
|
+
Generates:
|
22
|
+
* config/chimpactions.yml config file
|
23
|
+
|
24
|
+
h3. ActiveRecord store
|
25
|
+
|
26
|
+
<code>rails generate chimpactions:migration </code>
|
27
|
+
|
28
|
+
<code> rake db:migrate </code>
|
29
|
+
|
30
|
+
Generates:
|
31
|
+
* chimpactions ActiveRecord migration
|
32
|
+
|
33
|
+
h3. Customizing Admin
|
34
|
+
|
35
|
+
Chimpactions provides a basic scaffold for managing ActiveRecord Actions @ http:yourapp/chimpactions.
|
36
|
+
To override the gem views :
|
37
|
+
|
38
|
+
<code>rails generate chimpactions:customize </code>
|
39
|
+
|
40
|
+
Generates:
|
41
|
+
|
42
|
+
* chimpactions view files for administrative interface
|
43
|
+
* yourapp/app/views/chimpactions
|
44
|
+
|
45
|
+
h2. Configuration
|
46
|
+
|
47
|
+
_See installed config/chimpactions.yml for configuration options_
|
48
|
+
|
49
|
+
h2. Usage
|
50
|
+
|
51
|
+
h3. What's available
|
52
|
+
|
53
|
+
Once defined (in chimpactions.yml) the local Rails model inherits the following methods from the Chimpactions gem :
|
54
|
+
* add_to(List)
|
55
|
+
* move_to(List)
|
56
|
+
* remove_from(List)
|
57
|
+
|
58
|
+
h3. A Chimpaction :
|
59
|
+
|
60
|
+
*WHENN (A model method/attribute) IS (<,>,=) VALUE, ACTION (Chimpactions method) LIST (One of your MailChimp Lists)*
|
61
|
+
|
62
|
+
ex.
|
63
|
+
|
64
|
+
'When a user has more than 50 posts, move them to the Power Poster list'
|
65
|
+
|
66
|
+
*_in chimpactions.yml_*
|
67
|
+
<pre><code> action:
|
68
|
+
-
|
69
|
+
action: :move_to,
|
70
|
+
list: Power Posters,
|
71
|
+
whenn: posts.count,
|
72
|
+
is: >,
|
73
|
+
value: 50
|
74
|
+
-
|
75
|
+
</code></pre>
|
76
|
+
|
77
|
+
*_for ActiveRecord store_*
|
78
|
+
The admin interface should be a straightforward representation.
|
79
|
+
|
80
|
+
h3. Administrative Interface
|
81
|
+
|
82
|
+
Direct your browser to http://yourapp.chimpactions for a simple CRUD to build and manage Actions.
|
83
|
+
Available values are set in the forms where applicable, validations will tell you if a value won't work.
|
84
|
+
|
85
|
+
h3. Manual access
|
86
|
+
|
87
|
+
You can move subscribers around arbitrarily as well:
|
88
|
+
|
89
|
+
<pre><code>user = User.find(123)
|
90
|
+
user.remove_from("Power Posters")
|
91
|
+
</code></pre>
|
92
|
+
|
93
|
+
h3. Chimpactions Module
|
94
|
+
|
95
|
+
All your lists with a ton of info:
|
96
|
+
<pre><code>@lists = Chimpactions.available_lists
|
97
|
+
...view
|
98
|
+
<%= var_dump(@lists) ->
|
99
|
+
</code></pre>
|
100
|
+
|
101
|
+
Calling the MailChimp API directly:
|
102
|
+
|
103
|
+
Direct access to the "gibbon":http://rubygems.org/gems/gibbon/ socket :
|
104
|
+
<pre><code>api_result = Chimpactions.socket.campaigns({:start => 0, :limit => 100})
|
105
|
+
</code></pre>
|
106
|
+
|
107
|
+
|
108
|
+
h3. Webhooks
|
109
|
+
|
110
|
+
To register your application with your MailChimp List direct your browser to : http://yourapp/chimpactions/webhooks
|
111
|
+
|
112
|
+
The links next to each list will add/delete the webhook http://yourapp/chimpactions/receive to that list.
|
113
|
+
|
114
|
+
You must handle the post itself in <pre><code> receive_webhook(mc_post_data) </code> </pre> in your mix-in model for it have an effect.
|
115
|
+
|
116
|
+
|
117
|
+
h2. TODO
|
118
|
+
|
119
|
+
* implement VCR for tests so we don't have to use a real API key
|
120
|
+
* get loading don't so we don't have to add <code>include Chimpactions::Subscriber</code> in the model
|
121
|
+
|
122
|
+
h2. License
|
123
|
+
|
124
|
+
This project released under the MIT-LICENSE.
|
125
|
+
|
126
|
+
h2. Thanks
|
127
|
+
|
128
|
+
p. Made possible by the generous support of the "MailChimp Integration Fund":http://www.mailchimp.com/about/integration-fund/ .
|
129
|
+
|
130
|
+
h2. Copyrights
|
131
|
+
|
132
|
+
(c) circuitllc & "imgenius":http://imgeni.us 2011 - Released under the MIT license.
|
133
|
+
|
134
|
+
|
data/Rakefile
CHANGED
@@ -1,2 +1,46 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'rubygems'
|
3
|
+
begin
|
4
|
+
require 'bundler/setup'
|
5
|
+
rescue LoadError
|
6
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
7
|
+
end
|
8
|
+
|
1
9
|
require 'bundler'
|
2
10
|
Bundler::GemHelper.install_tasks
|
11
|
+
|
12
|
+
require 'rake'
|
13
|
+
require 'rake/rdoctask'
|
14
|
+
|
15
|
+
require 'rake/testtask'
|
16
|
+
|
17
|
+
Rake::TestTask.new(:test) do |t|
|
18
|
+
t.libs << 'lib'
|
19
|
+
t.libs << 'test'
|
20
|
+
t.pattern = 'test/**/*_test.rb'
|
21
|
+
t.verbose = false
|
22
|
+
end
|
23
|
+
|
24
|
+
Rake::TestTask.new(:units) do |t|
|
25
|
+
t.libs << 'lib'
|
26
|
+
t.libs << 'test'
|
27
|
+
t.pattern = 'test/unit/*_test.rb'
|
28
|
+
t.verbose = false
|
29
|
+
end
|
30
|
+
|
31
|
+
Rake::TestTask.new(:functionals) do |t|
|
32
|
+
t.libs << 'lib'
|
33
|
+
t.libs << 'test'
|
34
|
+
t.pattern = 'test/integration/*_test.rb'
|
35
|
+
t.verbose = false
|
36
|
+
end
|
37
|
+
|
38
|
+
task :default => :test
|
39
|
+
|
40
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
41
|
+
rdoc.rdoc_dir = 'rdoc'
|
42
|
+
rdoc.title = 'Chimpactions'
|
43
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
44
|
+
rdoc.rdoc_files.include('README.rdoc')
|
45
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
46
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
class ChimpactionsController < ApplicationController
|
2
|
+
def index
|
3
|
+
@all_actions = Chimpactions.actions
|
4
|
+
@registered = Chimpactions.registered_class_name
|
5
|
+
@actions = Chimpaction.all
|
6
|
+
@lists = Chimpactions.available_lists
|
7
|
+
end
|
8
|
+
|
9
|
+
# GET /chimpactions/new
|
10
|
+
# GET /chimpactions/new.xml
|
11
|
+
def new
|
12
|
+
@chimpaction = Chimpaction.new
|
13
|
+
|
14
|
+
respond_to do |format|
|
15
|
+
format.html # new.html.erb
|
16
|
+
format.xml { render :xml => @chimpaction }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# GET /chimpactions/1/edit
|
21
|
+
def edit
|
22
|
+
@chimpaction = Chimpaction.find(params[:id])
|
23
|
+
end
|
24
|
+
|
25
|
+
# POST /chimpactions
|
26
|
+
# POST /chimpactions.xml
|
27
|
+
def create
|
28
|
+
@chimpaction = Chimpaction.new(params[:chimpaction])
|
29
|
+
|
30
|
+
respond_to do |format|
|
31
|
+
if @chimpaction.save
|
32
|
+
format.html { redirect_to(chimpactions_url, :notice => 'Chimpaction was successfully created.') }
|
33
|
+
format.xml { render :xml => @chimpaction, :status => :created, :location => @chimpaction }
|
34
|
+
else
|
35
|
+
format.html { render :action => "new" }
|
36
|
+
format.xml { render :xml => @chimpaction.errors, :status => :unprocessable_entity }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# PUT /chimpactions/1
|
42
|
+
# PUT /chimpactions/1.xml
|
43
|
+
def update
|
44
|
+
@chimpaction = Chimpaction.find(params[:id])
|
45
|
+
|
46
|
+
respond_to do |format|
|
47
|
+
if @chimpaction.update_attributes(params[:chimpaction])
|
48
|
+
format.html { redirect_to(chimpactions_url, :notice => 'Chimpaction was successfully updated.') }
|
49
|
+
format.xml { head :ok }
|
50
|
+
else
|
51
|
+
format.html { render :action => "edit" }
|
52
|
+
format.xml { render :xml => @chimpaction.errors, :status => :unprocessable_entity }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# DELETE /chimpactions/1
|
58
|
+
# DELETE /chimpactions/1.xml
|
59
|
+
def destroy
|
60
|
+
@chimpaction = Chimpaction.find(params[:id])
|
61
|
+
@chimpaction.destroy
|
62
|
+
|
63
|
+
respond_to do |format|
|
64
|
+
format.html { redirect_to(chimpactions_url) }
|
65
|
+
format.xml { head :ok }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def webhooks
|
70
|
+
@lists = Chimpactions.available_lists
|
71
|
+
end
|
72
|
+
|
73
|
+
def add_webhook
|
74
|
+
list = Chimpactions.list(params[:id])
|
75
|
+
if list.set_webhook :url => 'http://www.postbin.org/1iwea1s'#webhook_url
|
76
|
+
flash[:notice] = "Added Webhook!"
|
77
|
+
end
|
78
|
+
redirect_to '/chimpactions/webhooks'
|
79
|
+
end
|
80
|
+
|
81
|
+
def delete_webhook
|
82
|
+
list = Chimpactions.list(params[:id])
|
83
|
+
if list.remove_webhook :url => 'http://www.postbin.org/1iwea1s' #webhook_url
|
84
|
+
flash[:notice] = "Removed Webhook!"
|
85
|
+
end
|
86
|
+
redirect_to '/chimpactions/webhooks'
|
87
|
+
end
|
88
|
+
|
89
|
+
def receive
|
90
|
+
if params['data']
|
91
|
+
subscriber = Chimpactions.registered_class.find_by_email(params['data']['email'])
|
92
|
+
subscriber.receive_webhook(params) if subscriber.respond_to?(:receive_webhook)
|
93
|
+
end
|
94
|
+
render :nothing => true
|
95
|
+
end
|
96
|
+
# data[email] = 'federico@mailchimp.com'
|
97
|
+
#
|
98
|
+
# data[email_type] = 'html'
|
99
|
+
#
|
100
|
+
# data[id] = 'da1b07ac4c'
|
101
|
+
#
|
102
|
+
# data[ip_opt]='69.12.4.2'
|
103
|
+
#
|
104
|
+
# data[list_id]='45a650bc63'
|
105
|
+
#
|
106
|
+
# data[merges][EMAIL]='federico@mailchimp.com'
|
107
|
+
#
|
108
|
+
# data[merges][FNAME] ='Federico'
|
109
|
+
#
|
110
|
+
# data[merges][IP] ='127.0.0.1'
|
111
|
+
#
|
112
|
+
# data[merges][LNAME]='Holgado'
|
113
|
+
#
|
114
|
+
# data[merges][SIGNUP]=''
|
115
|
+
#
|
116
|
+
# data[web_id]='234305517'
|
117
|
+
#
|
118
|
+
# fired_at = '2011-06-30 02:34:35'
|
119
|
+
#
|
120
|
+
# type ='profile'
|
121
|
+
# end
|
122
|
+
|
123
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "chimpactions"
|
2
|
+
|
3
|
+
class ResponseValidator < ActiveModel::Validator
|
4
|
+
def validate(record)
|
5
|
+
# k = Kernel.const_get(Chimpactions::registered_class.name.to_s.capitalize).new
|
6
|
+
k = Chimpactions.registered_class
|
7
|
+
if k.respond_to?(record.action) != true
|
8
|
+
record.errors[:action] << "- '#{record.action}' is not a method of #{k.class.name} !"
|
9
|
+
end
|
10
|
+
if k.respond_to?(record.whenn) != true
|
11
|
+
record.errors[:whenn] << "- '#{record.whenn}' is not a method of #{k.class.name} !"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# ActiveRecord 'wrapper' for Chimpactions::Action to provide non-yml peristence & customization
|
17
|
+
class Chimpaction < ActiveRecord::Base
|
18
|
+
validates_presence_of :list, :action, :whenn, :is, :value
|
19
|
+
validates_with ResponseValidator
|
20
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<% if target.errors.any? %>
|
2
|
+
<div id="errorExplanation">
|
3
|
+
<h2><%= pluralize(target.errors.count, "error") %> prohibited this record from being saved:</h2>
|
4
|
+
<ul>
|
5
|
+
<% target.errors.full_messages.each do |msg| %>
|
6
|
+
<li><%= msg %></li>
|
7
|
+
<% end %>
|
8
|
+
</ul>
|
9
|
+
</div>
|
10
|
+
<% end %>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<style>
|
2
|
+
.ca_action_form {padding-bottom:25px;width:350px;}
|
3
|
+
.ca_action_form fieldset {background-color:inherit;padding:0px;margin:0px;}
|
4
|
+
.ca_action_form fieldset legend {background-color:inherit;}
|
5
|
+
.ca_action_form * {float:none;font-family: verdana, arial, helvetica, sans-serif;
|
6
|
+
font-size: 12px!important;
|
7
|
+
line-height: 14px!important;}
|
8
|
+
.ca_action_form label {padding:0 4px;}
|
9
|
+
.ca_action_form div {display:inline;}
|
10
|
+
.ca_action_form .field_with_errors input {border:1px solid red;}
|
11
|
+
.ca_action_form ol {list-style:none;padding:14px;margin: 0px auto;max-width:315px;}
|
12
|
+
.ca_action_form ol li{padding:4px;}
|
13
|
+
.ca_action_form .bold {font-weight:bold;}
|
14
|
+
</style>
|
15
|
+
<%= form_for @chimpaction, :html => {:class => 'ca_action_form'} do |c| %>
|
16
|
+
<%= render "chimpactions/errors", :target => @chimpaction %>
|
17
|
+
<fieldset>
|
18
|
+
<ol>
|
19
|
+
<li><%= c.label :when, {:class => 'bold'} %> <%= Chimpactions.registered_class_name%>.<%= c.text_field :whenn, {:size => '15'} %> </li>
|
20
|
+
<li><%= select(:chimpaction, :is, %w(= < >)) %> <%= c.text_field :value %><%= c.label '(Value)' %></li>
|
21
|
+
<li><%= c.label "THEN", {:class => 'bold'}%></li>
|
22
|
+
<li><%= select(:chimpaction, :action, %w(add_to move_to remove_from).map {|l| [l.gsub('_',' ').titleize , l]}) -%></li>
|
23
|
+
<li><%= collection_select(:chimpaction, :list, Chimpactions.available_lists, :name, :name)%></li>
|
24
|
+
<li><%= submit_tag "submit"%></li>
|
25
|
+
</fieldset>
|
26
|
+
<% end %>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<section>
|
2
|
+
<% %w(notice warning error).each do |msg| %>
|
3
|
+
<% unless flash[msg.to_sym].blank? %>
|
4
|
+
<div class='message <%=msg-%>'><p><%=flash[msg.to_sym]-%></p></div>
|
5
|
+
<% end %>
|
6
|
+
<% end %>
|
7
|
+
<h1>Current Chimpactions : </h1>
|
8
|
+
<ul>
|
9
|
+
<% @actions.each do |action|%>
|
10
|
+
<li> When a <%= @registered %> <%= action.whenn %> <%= action.is %> <%= action.value %> => <%= @registered%>.<%= action.action %> (<%= action.list %>)
|
11
|
+
<%= link_to 'Edit', edit_chimpaction_path(action) %> ||
|
12
|
+
<%= link_to 'Destroy', chimpaction_path(action.id), :confirm => 'Are you sure?', :method => :delete %></li>
|
13
|
+
<%end%>
|
14
|
+
</ul>
|
15
|
+
</section>
|
16
|
+
<section>
|
17
|
+
<h1> <%= link_to "Add New Chimpaction", new_chimpaction_path %> </h1>
|
18
|
+
</section>
|
19
|
+
<section>
|
20
|
+
<h1>Your MailChimp lists: </h1>
|
21
|
+
<%= render :partial => 'list', :collection => @lists if @lists.count > 0%>
|
22
|
+
</section>
|