chimpactions 0.0.0 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/Gemfile +14 -2
  2. data/MIT-LICENSE +20 -0
  3. data/README.textile +134 -0
  4. data/Rakefile +44 -0
  5. data/app/controllers/chimpactions_controller.rb +123 -0
  6. data/app/models/chimpaction.rb +20 -0
  7. data/app/views/chimpactions/_errors.html.erb +10 -0
  8. data/app/views/chimpactions/_form.html.erb +26 -0
  9. data/app/views/chimpactions/_list.html.erb +6 -0
  10. data/app/views/chimpactions/edit.html.erb +4 -0
  11. data/app/views/chimpactions/index.html.erb +22 -0
  12. data/app/views/chimpactions/new.html.erb +4 -0
  13. data/app/views/chimpactions/webhooks.html.erb +26 -0
  14. data/chimpactions.gemspec +9 -4
  15. data/config/deploy/templates/nginx.conf.tpl_ +0 -0
  16. data/config/deploy/templates/unicorn.conf.tpl_ +0 -0
  17. data/config/routes.rb +8 -0
  18. data/lib/chimpactions.rb +210 -2
  19. data/lib/chimpactions/action.rb +73 -0
  20. data/lib/chimpactions/engine.rb +21 -0
  21. data/lib/chimpactions/exception.rb +14 -0
  22. data/lib/chimpactions/list.rb +113 -0
  23. data/lib/chimpactions/notifier.rb +9 -0
  24. data/lib/chimpactions/setup.rb +42 -0
  25. data/lib/chimpactions/subscriber.rb +125 -0
  26. data/lib/chimpactions/utility.rb +13 -0
  27. data/lib/chimpactions/version.rb +1 -1
  28. data/lib/generators/chimpactions/customize/customize_generator.rb +19 -0
  29. data/lib/generators/chimpactions/customize/templates/views/_errors.html.erb +10 -0
  30. data/lib/generators/chimpactions/customize/templates/views/_form.html.erb +26 -0
  31. data/lib/generators/chimpactions/customize/templates/views/_list.html.erb +6 -0
  32. data/lib/generators/chimpactions/customize/templates/views/edit.html.erb +4 -0
  33. data/lib/generators/chimpactions/customize/templates/views/index.html.erb +22 -0
  34. data/lib/generators/chimpactions/customize/templates/views/new.html.erb +4 -0
  35. data/lib/generators/chimpactions/customize/templates/views/webhooks.html.erb +26 -0
  36. data/lib/generators/chimpactions/install/install_generator.rb +19 -0
  37. data/lib/generators/chimpactions/install/templates/README +10 -0
  38. data/lib/generators/chimpactions/install/templates/chimpactions.yml +39 -0
  39. data/lib/generators/chimpactions/install/templates/chimpactions_initializer.rb +1 -0
  40. data/lib/generators/chimpactions/migration/migration_generator.rb +26 -0
  41. data/lib/generators/chimpactions/migration/templates/create_chimpactions.rb +16 -0
  42. data/lib/railtie.rb +16 -0
  43. metadata +82 -38
  44. data/.gitignore +0 -4
data/Gemfile CHANGED
@@ -1,4 +1,16 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- # Specify your gem's dependencies in chimpactions.gemspec
4
- gemspec
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,6 @@
1
+ <style>
2
+ .ca_list {list-style:none;padding:0px;}
3
+ </style>
4
+ <ul class="ca_list">
5
+ <li><%= list.name%> ( ID : <%= list.id %> )</li>
6
+ </ul>
@@ -0,0 +1,4 @@
1
+ <section>
2
+ <h1>EDIT Chimpaction : </h1>
3
+ <%= render :partial => 'form'%>
4
+ </section>
@@ -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>