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
@@ -0,0 +1,9 @@
1
+ module Chimpactions
2
+ # Notifier for telling the List objects that Chimpactions is using a new connection.
3
+ class ListNotifier
4
+ # Notify the List class that we havea new connection to MailChimp
5
+ def update(chimpactions)
6
+ chimpactions::List.new_socket
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,42 @@
1
+ module Chimpactions
2
+ #Utility class for ensuring everythign is ready for Chimpactions to do its work
3
+ module Setup
4
+ mattr_accessor :message
5
+ mattr_reader :errors
6
+ @@errors = ActiveSupport::OrderedHash.new
7
+
8
+ # Make sure we have the right info to proceed.
9
+ def self.ensure_initialization
10
+ @@errors = ActiveSupport::OrderedHash.new
11
+ self.error(:api_key, "Is not set!") if Chimpactions.mailchimp_api_key == "your_mailchimp_api_key" || Chimpactions.mailchimp_api_key.nil?
12
+ self.error(:ses_key, "Is not set!") if Chimpactions.mailchimp_ses_key == "your_mailchimp_ses_key" || Chimpactions.mailchimp_ses_key.nil?
13
+ # self.verify_api_key
14
+ @@message = "Chimpactions::Setup.initialize"
15
+ end
16
+
17
+ # Were there errors in the setup ?
18
+ def self.ok?
19
+ errors.empty?
20
+ end
21
+
22
+ # Check the gibbon connection to MailChimp
23
+ # Verify that the API key is good.
24
+ def self.verify
25
+ begin
26
+ Chimpactions.socket.chimpChatter()
27
+ rescue Exception => e
28
+ self.error(:api_key,"BAD API KEY::" << e.message)
29
+ false
30
+ end
31
+ end
32
+
33
+ private
34
+ # Register an error in the setup.
35
+ def self.error(parameter,message)
36
+ errors[parameter] = message
37
+ end
38
+
39
+
40
+
41
+ end
42
+ end
@@ -0,0 +1,125 @@
1
+ module Chimpactions
2
+ #The Chimpactions Subscriber is the mix-in module for a
3
+ # local model.
4
+ #Once initialized, the local model inherits all Subscriber methods.
5
+ #ex.
6
+ #<pre>
7
+ # see chimpaction.yml for initializtaion options
8
+ #</pre>
9
+ module Subscriber
10
+
11
+ attr_accessor :merge_vars
12
+
13
+ # override for mix-in goodeness
14
+ def self.included(mod)
15
+ mod.send(:include, ClassMethods)
16
+ end
17
+
18
+ # listSubscribe(string apikey, string id, string email_address, array merge_vars, string email_type, bool double_optin, bool update_existing, bool replace_interests, bool send_welcome)
19
+ #
20
+ # Subscribe the provided email to a list.
21
+ #
22
+ # listUnsubscribe(string apikey, string id, string email_address, boolean delete_member, boolean send_goodbye, boolean send_notify)
23
+ #
24
+ # Unsubscribe the given email address from the list
25
+ module ClassMethods
26
+ def chimpactions
27
+ Chimpactions.actions.each{|action| action.execute(self)}
28
+ end
29
+
30
+ # Add the Subscriber to the specified list.
31
+ # @param [String, Fixnum, Chimpactions::List] list
32
+ def add_to(list, opts={})
33
+ list = validate_list(list)
34
+ list.socket.listSubscribe({:id => list.id, :email_address => self.email,
35
+ :merge_vars => self.merge_vars, :send_welcome => Chimpactions.default_send_welcome,
36
+ :double_optin => Chimpactions.default_double_optin,
37
+ :update_existing => Chimpactions.default_update_existing}.merge opts) == "true"
38
+ end
39
+
40
+ # Remove Subscriber from all lists in the account and add to the specified List
41
+ # @param [String, Fixnum, Chimpactions::List] list
42
+ def move_to(list)
43
+ list = validate_list(list)
44
+ # add to the specified list
45
+ if add_to(list) == true
46
+ #remove from all the others
47
+ Chimpactions.available_lists.each do |l|
48
+ remove_from(l) if l != list
49
+ end
50
+ true
51
+ else
52
+ false
53
+ end
54
+ end
55
+
56
+ # Remove the Subscriber from the specified list.
57
+ # @param [String, Fixnum, Chimpactions::List] list
58
+ def remove_from(list, opts={})
59
+ list = validate_list(list)
60
+ list.socket.listUnsubscribe({:id => list.id, :email_address => self.email}.merge opts) == "true"
61
+ end
62
+
63
+ # Send the specified MailChimp pre-defined "Response Email" to this Subscriber
64
+ # @param [String, Fixnum, Chimpactions::List] list
65
+ def send_response_email(list, title)
66
+ list = validate_list(list)
67
+ false # stub for test failure
68
+ end
69
+
70
+ # Check if this Subscriber is on the specified list.
71
+ # @param [String, Fixnum, Chimpactions::List] list
72
+ # @return [Boolean]
73
+ def on_list?(list, opts={})
74
+ list = validate_list(list)
75
+ answer = list.socket.listMemberInfo({:id => list.id, :email_address => self.email}.merge opts)
76
+ answer['success'] == 1 && answer['errors'] == 0
77
+ end
78
+
79
+ # Check if this Subscriber is 'subscribed' to the list.
80
+ # @param [String, Fixnum, Chimpactions::List] list
81
+ # @return [Boolean]
82
+ def subscribed?(list,opts={})
83
+ list = validate_list(list)
84
+ answer = list.socket.listMemberInfo({:id => list.id, :email_address => self.email}.merge opts)
85
+ answer['success'] == 1 && answer['data'][0]['status'] == 'subscribed'
86
+ end
87
+
88
+ # @param [Hash] hash The Chimpactions mergemap
89
+ def merge_vars(hash = Chimpactions.merge_map)
90
+ collect_merge_vars(hash)
91
+ end
92
+
93
+ private
94
+
95
+ # Sync this Subscriber's info to the MailChimp list.
96
+ # @return [boolean] *true* or *false*
97
+ def sync_to_chimp
98
+ Chimpactions.available_lists.each do |l|
99
+ add_to(l)
100
+ end
101
+ end
102
+
103
+
104
+ # Calls the specified method/attribute on the mix-in target
105
+ # @param [Hash] {'MAILCHIMP_MERGE_VAR' => 'model_attribute_or_method'}
106
+ # @return [Hash]
107
+ def collect_merge_vars(merge_hash)
108
+ merge_vars = Hash.new
109
+ merge_hash.each_pair do |key,val|
110
+ if self.respond_to?(val)
111
+ method_object = self.method(val.to_sym)
112
+ merge_vars[key] = method_object.call
113
+ end
114
+ end
115
+ merge_vars
116
+ end
117
+
118
+ # Wrapper for Chimpactions module list method
119
+ # @see Chimpactions.list(list)
120
+ def validate_list(list)
121
+ Chimpactions.list(list)
122
+ end
123
+ end
124
+ end #Module
125
+ end #Module
@@ -0,0 +1,13 @@
1
+ module Chimpactions
2
+ # Utility mix-in module
3
+ # Defines method_missing for accessing raw MC data as
4
+ # Object attributes.
5
+ module Utility
6
+ # Convenience method for accessing MailChimp data arrays
7
+ # as class attributes.
8
+ # ex. => List.id instead of List['id']
9
+ def method_missing(m, *args)
10
+ @raw.keys.include?(m.to_s) ? @raw[m.to_s] : super
11
+ end
12
+ end
13
+ end
@@ -1,3 +1,3 @@
1
1
  module Chimpactions
2
- VERSION = "0.0.0"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -0,0 +1,19 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+ module Chimpactions
4
+ module Generators
5
+ class CustomizeGenerator < Rails::Generators::Base
6
+ include Rails::Generators::Migration
7
+ source_root File.expand_path('../templates/views', __FILE__)
8
+ def copy_views
9
+ # Views template
10
+ copy_file "index.html.erb", "app/views/chimpactions/index.html.erb"
11
+ copy_file "edit.html.erb", "app/views/chimpactions/edit.html.erb"
12
+ copy_file "new.html.erb", "app/views/chimpactions/new.html.erb"
13
+ copy_file "_form.html.erb", "app/views/chimpactions/_form.html.erb"
14
+ copy_file "_errors.html.erb", "app/views/chimpactions/_errors.html.erb"
15
+ copy_file "webhooks.html.erb", "app/views/chimpactions/webhooks.html.erb"
16
+ end
17
+ end
18
+ end
19
+ 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>
@@ -0,0 +1,4 @@
1
+ <section>
2
+ <h1>Create a Chimpaction : </h1>
3
+ <%= render :partial => 'form'%>
4
+ </section>
@@ -0,0 +1,26 @@
1
+ <style>
2
+ .ca_list {list-style:none;padding:0px;}
3
+ </style>
4
+ <div style="font-size:1.2em; color:green;"><%= flash[:notice] if flash[:notice] %></div>
5
+ <ul class="ca_list">
6
+ <% @lists.each do |list|%>
7
+ <li><%= list.name%> ( ID : <%= list.id %> )
8
+ <% if list.webhook? == false %>
9
+ <%=link_to "Add Webhook", {:action => 'add_webhook', :id => list.web_id }%>
10
+ <% else %>
11
+ <%=link_to "REMOVE Webhook", {:action => 'delete_webhook', :id => list.web_id }%>
12
+ <%end%>
13
+ </li>
14
+ <%end%>
15
+ </ul>
16
+
17
+ <div style="margin-top:25px;"> Remember ! : in order to do something here, your <%= Chimpactions.registered_class_name %> class must define :
18
+ <pre>
19
+ ...
20
+ def receive_webhook(post_from_mailchimp)
21
+ // do something with the MailChimp POST data here
22
+ end
23
+ ...
24
+ </pre>
25
+
26
+ </div>
@@ -0,0 +1,19 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+ module Chimpactions
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ include Rails::Generators::Migration
7
+ source_root File.expand_path('../templates', __FILE__)
8
+
9
+ desc "Creates a Chimpactions initializer and copy locale files to your application."
10
+ def copy_config_yml
11
+ copy_file "chimpactions.yml", "config/chimpactions.yml"
12
+ end
13
+
14
+ def show_readme
15
+ readme "README" if behavior == :invoke
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,10 @@
1
+ ===============================================================================
2
+ Chimpactions is almost ready...
3
+
4
+ - Edit config/chimpactions.yml accordingly
5
+ - To use ActiveRecord data store for Actions:
6
+ - rails generate chimpactions:migration
7
+ - you can then visit the admin interface at http:yourapp/chimpactions
8
+ - To customize the Admin section above:
9
+ - rails generate chimpactions:customize
10
+ ===============================================================================
@@ -0,0 +1,39 @@
1
+ mailchimp_api_key: your_mailchimp_api_key
2
+ mailchimp_ses_key: your_mailchimp_ses_key
3
+ # Mappings of YOUR MailChimp Merge Variables
4
+ # => This list should include ANY merge variables throughout your MailChimp
5
+ # account from any and all lists.
6
+ # => Chimpactions will fail gracefully (i.e. not try to send) on any varibles
7
+ # either not set by your model, or not in the particular list.
8
+ # => If your model does not respond_to?('your_models_attribute_or_method')
9
+ # the merge variable will be skipped (not sent).
10
+ # @format :: MAILCHIMP_MERGE_VAR: 'model_attribute_or_method'
11
+ merge_map:
12
+ FNAME: first_name
13
+ LNAME: last_name
14
+ EMAIL: email
15
+ FAV_COL: favorite_color
16
+ # The local model to target for mix-in of the Chimpactions gem.
17
+ # This effectively makes the defined model as a Chimpactions::Subscriber
18
+ local_model: YourLocalModel
19
+ default_double_optin: false #default false Require the user to reply to the MailChimp system before adding to list.
20
+ default_send_welcome: true #default true Have MailChimp send the "Welcome" email for the list immediately.
21
+ default_email_type: html # 'nuff said... html ot text
22
+ # Storage method for Chimpactions persistence
23
+ # => :active_record OR :yml
24
+ # :active_record => ActiveRecord DB model (see migration)
25
+ # :yml => manually defined in this file with :
26
+ # actions:
27
+ # -
28
+ # action: :move_to
29
+ # list: "A MailChimp List Name"
30
+ # whenn: "your_method_or_attribute_1"
31
+ # is: '='
32
+ # value: 'the_value_1'
33
+ # -
34
+ # action: :remove_from
35
+ # list: "Another MailChimp List Name"
36
+ # whenn: "your_method_or_attribute_2"
37
+ # is: '='
38
+ # value: 'the_value_2'
39
+ action_store: :yml
@@ -0,0 +1 @@
1
+ ChimpactionsController.send(:before_filter, 'require_admin')
@@ -0,0 +1,26 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+ module Chimpactions
4
+ module Generators
5
+ class MigrationGenerator < Rails::Generators::Base
6
+ include Rails::Generators::Migration
7
+ source_root File.expand_path('../templates', __FILE__)
8
+
9
+ desc "add the migrations"
10
+ def self.next_migration_number(path)
11
+ unless @prev_migration_nr
12
+ @prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
13
+ else
14
+ @prev_migration_nr += 1
15
+ end
16
+ @prev_migration_nr.to_s
17
+ end
18
+
19
+ desc "Add the Chimpactions migration to Rails db/migrate"
20
+ def copy_migrations
21
+ migration_template "create_chimpactions.rb", "db/migrate/create_chimpactions.rb"
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,16 @@
1
+ class CreateChimpactions < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :chimpactions, :force => true do |t|
4
+ t.text :action
5
+ t.text :list
6
+ t.string :whenn
7
+ t.string :is
8
+ t.string :value
9
+ t.timestamps
10
+ end
11
+ end
12
+
13
+ def self.down
14
+ drop_table :chimpactions
15
+ end
16
+ end