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.
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