subscribed_to 0.2.0 → 0.3.0
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 +1 -0
- data/Gemfile.lock +2 -0
- data/README.rdoc +32 -0
- data/app/controllers/subscribed_to/mail_chimp_web_hooks_controller.rb +19 -0
- data/config/routes.rb +5 -0
- data/lib/active_record_extensions.rb +10 -0
- data/lib/generators/subscribed_to/templates/migration.rb +8 -0
- data/lib/generators/subscribed_to/templates/subscribed_to.rb +4 -0
- data/lib/subscribed_to/engine.rb +7 -0
- data/lib/subscribed_to/mail_chimp/config.rb +5 -3
- data/lib/subscribed_to/mail_chimp/web_hook.rb +136 -0
- data/lib/subscribed_to/mail_chimp.rb +3 -2
- data/lib/subscribed_to/version.rb +1 -1
- data/lib/subscribed_to.rb +9 -0
- data/spec/app/controllers/subscribed_to/mail_chimp_web_hooks_spec.rb +147 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/user.rb +3 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config/application.rb +45 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +22 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +26 -0
- data/spec/dummy/config/environments/production.rb +49 -0
- data/spec/dummy/config/environments/test.rb +35 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +10 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/subscribed_to.rb +21 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +2 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/migrate/1_create_users.rb +18 -0
- data/spec/dummy/db/schema.rb +26 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/javascripts/application.js +2 -0
- data/spec/dummy/public/javascripts/controls.js +965 -0
- data/spec/dummy/public/javascripts/dragdrop.js +974 -0
- data/spec/dummy/public/javascripts/effects.js +1123 -0
- data/spec/dummy/public/javascripts/prototype.js +6001 -0
- data/spec/dummy/public/javascripts/rails.js +191 -0
- data/spec/dummy/public/stylesheets/.gitkeep +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/factories/users.rb +1 -0
- data/spec/{generators → lib/generators}/install_generator_spec.rb +0 -0
- data/spec/{subscribed_to → lib/subscribed_to}/mail_chimp/config_spec.rb +0 -0
- data/spec/lib/subscribed_to/mail_chimp/web_hook_spec.rb +158 -0
- data/spec/lib/subscribed_to/mail_chimp_spec.rb +74 -0
- data/spec/{subscribed_to_spec.rb → lib/subscribed_to_spec.rb} +0 -0
- data/spec/spec_helper.rb +70 -28
- data/subscribed_to.gemspec +136 -0
- metadata +77 -26
- data/spec/app/models/user.rb +0 -43
- data/spec/database.yml.example +0 -17
- data/spec/schema.rb +0 -9
- data/spec/subscribed_to/mail_chimp_spec.rb +0 -53
data/Gemfile
CHANGED
@@ -7,6 +7,7 @@ gem "hominid", ">= 3.0.2"
|
|
7
7
|
# Include everything needed to run rake, tests, features, etc.
|
8
8
|
group :development do
|
9
9
|
gem "sqlite3-ruby", :require => "sqlite3"
|
10
|
+
gem 'database_cleaner'
|
10
11
|
gem "factory_girl_rails", "1.0.1"
|
11
12
|
gem "mocha", "0.9.12"
|
12
13
|
gem "rspec-rails", "2.5.0"
|
data/Gemfile.lock
CHANGED
@@ -30,6 +30,7 @@ GEM
|
|
30
30
|
activesupport (3.0.7)
|
31
31
|
arel (2.0.9)
|
32
32
|
builder (2.1.2)
|
33
|
+
database_cleaner (0.6.7)
|
33
34
|
diff-lcs (1.1.2)
|
34
35
|
erubis (2.6.6)
|
35
36
|
abstract (>= 1.0.0)
|
@@ -110,6 +111,7 @@ PLATFORMS
|
|
110
111
|
DEPENDENCIES
|
111
112
|
activerecord
|
112
113
|
bundler (~> 1.0.0)
|
114
|
+
database_cleaner
|
113
115
|
factory_girl_rails (= 1.0.1)
|
114
116
|
generator_spec
|
115
117
|
hanna
|
data/README.rdoc
CHANGED
@@ -30,6 +30,8 @@ API v1.3 - http://apidocs.mailchimp.com/1.3
|
|
30
30
|
* listUpdateMember
|
31
31
|
|
32
32
|
|
33
|
+
Adds support for MailChimp webhooks
|
34
|
+
|
33
35
|
<b>Constant Contact</b>
|
34
36
|
|
35
37
|
Planned
|
@@ -78,6 +80,36 @@ Set up your mailing lists to subscribe users to. List names can be any valid sym
|
|
78
80
|
:id => "xxxxxxxx",
|
79
81
|
:merge_vars => {"FNAME" => :first_name, "LNAME" => :last_name, "EMAIL" => :email}}}
|
80
82
|
|
83
|
+
Set your secret key for the webhook URL.
|
84
|
+
|
85
|
+
Keep this key a secret. It's the only line of defense of preventing unwanted POST requests to the URL.
|
86
|
+
|
87
|
+
mail_chimp_config.secret_key = "my_secret_key_that_i_will_change"
|
88
|
+
|
89
|
+
==== Webhooks
|
90
|
+
|
91
|
+
The gem sets up support for MailChimp webhooks. Read more here: http://apidocs.mailchimp.com/webhooks/
|
92
|
+
|
93
|
+
First, you need to setup webhooks in your MailChimp account.
|
94
|
+
|
95
|
+
1) On the list tools page, click the "WebHooks" link.
|
96
|
+
|
97
|
+
2) Enter the webhook URL as:
|
98
|
+
http://mywebapp.com/subscribed_to/mail_chimp?key=<secret_key_defined_in_config>
|
99
|
+
|
100
|
+
3) Enable updates for events:
|
101
|
+
* Subscribes
|
102
|
+
* Unsubscribes
|
103
|
+
* Profile Updates
|
104
|
+
* Email Changed
|
105
|
+
|
106
|
+
4) Send updates when a change was made by...
|
107
|
+
* A subscriber
|
108
|
+
* Account admin
|
109
|
+
* Via the API
|
110
|
+
|
111
|
+
5) Click "Update"
|
112
|
+
|
81
113
|
=== User Model Configuration
|
82
114
|
|
83
115
|
You must enable *SubscribedTo* in your user model with <tt>subscribed_to</tt>.
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module SubscribedTo
|
2
|
+
class MailChimpWebHooksController < ApplicationController
|
3
|
+
|
4
|
+
unloadable
|
5
|
+
|
6
|
+
# Handle MailChimp webhooks
|
7
|
+
# Requires a secret key be set in the SubscribedTo initializer.
|
8
|
+
# Include the secret key in the post URL for the webhook in your MailChimp account.
|
9
|
+
def create
|
10
|
+
key = params.delete("key")
|
11
|
+
unless key.blank? || key != SubscribedTo.mail_chimp_config.secret_key
|
12
|
+
SubscribedTo::MailChimp::WebHook.process(params)
|
13
|
+
render :text => nil, :status => 200
|
14
|
+
else
|
15
|
+
render :text => nil, :status => 404
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
module ActiveRecord #:nodoc:
|
2
|
+
module Persistence
|
3
|
+
# We need to skip the after_update callback here. Otherwise, we'll trigger a loop of MailChimp updates.
|
4
|
+
def save_without_update_list_member(options)
|
5
|
+
self.class.skip_callback(:update, :after, :update_list_member)
|
6
|
+
self.save(options)
|
7
|
+
self.class.set_callback(:update, :after, :update_list_member)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -1,9 +1,17 @@
|
|
1
1
|
class <%= migration_name.camelize %> < ActiveRecord::Migration
|
2
2
|
def self.up
|
3
3
|
add_column :<%= table_name.to_sym %>, :subscribed_to_list, :boolean, :default => false
|
4
|
+
<%- if options.service == "mail_chimp" -%>
|
5
|
+
add_column :<%= table_name.to_sym %>, :mail_chimp_id, :integer
|
6
|
+
add_index :<%= table_name.to_sym %>, :mail_chimp_id
|
7
|
+
<%- end -%>
|
4
8
|
end
|
5
9
|
|
6
10
|
def self.down
|
7
11
|
remove_column :<%= table_name.to_sym %>, :subscribed_to_list
|
12
|
+
<%- if options.service == "mail_chimp" -%>
|
13
|
+
remove_column :<%= table_name.to_sym %>, :mail_chimp_id, :integer
|
14
|
+
remove_index :<%= table_name.to_sym %>, :mail_chimp_id
|
15
|
+
<%- end -%>
|
8
16
|
end
|
9
17
|
end
|
@@ -16,6 +16,10 @@ SubscribedTo.setup do |config|
|
|
16
16
|
:mailing_list => {
|
17
17
|
:id => "xxxxxxxx",
|
18
18
|
:merge_vars => {"FNAME" => :first_name, "LNAME" => :last_name, "EMAIL" => :email}}}
|
19
|
+
|
20
|
+
# Include this key in your MailChimp webhook URL.
|
21
|
+
# Keep it a secret!
|
22
|
+
mail_chimp_config.secret_key = "my_secret_key_that_i_will_change"
|
19
23
|
end
|
20
24
|
<%- end -%>
|
21
25
|
end
|
@@ -17,12 +17,14 @@ module SubscribedTo
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
hash_accessor :api_key, :lists
|
20
|
+
hash_accessor :api_key, :lists, :secret_key, :enabled_models
|
21
21
|
|
22
22
|
def initialize(config = {})
|
23
23
|
merge!(config)
|
24
|
-
self[:api_key]
|
25
|
-
self[:lists]
|
24
|
+
self[:api_key] ||= nil
|
25
|
+
self[:lists] ||= {}
|
26
|
+
self[:secret_key] ||= "J/M7k+j8zBJI7SM5"
|
27
|
+
self[:enabled_models] ||= {}
|
26
28
|
end
|
27
29
|
end
|
28
30
|
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
module SubscribedTo
|
2
|
+
module MailChimp
|
3
|
+
|
4
|
+
# Allows for the usage of MailChimp webhooks.
|
5
|
+
# http://apidocs.mailchimp.com/webhooks/
|
6
|
+
#
|
7
|
+
# To get started:
|
8
|
+
#
|
9
|
+
# 1) On the list tools page, click the "WebHooks" link.
|
10
|
+
#
|
11
|
+
# 2) Enter the webhook URL as:
|
12
|
+
# http://mywebapp.com/subscribed_to/mail_chimp?key=<secret_key_defined_in_config>
|
13
|
+
#
|
14
|
+
# 3) Enable updates for events:
|
15
|
+
# * Subscribes
|
16
|
+
# * Unsubscribes
|
17
|
+
# * Profile Updates
|
18
|
+
# * Email Changed
|
19
|
+
#
|
20
|
+
# 4) Send updates when a change was made by...
|
21
|
+
# * A subscriber
|
22
|
+
# * Account admin
|
23
|
+
# * Via the API
|
24
|
+
#
|
25
|
+
# 5) Click "Update"
|
26
|
+
class WebHook
|
27
|
+
LIMIT = 120
|
28
|
+
attr_accessor :enabled_models
|
29
|
+
|
30
|
+
# Handles MailChimp webhook request.
|
31
|
+
# Takes in a hash of parameters from the webhook.
|
32
|
+
#
|
33
|
+
# Responds to four webhook events:
|
34
|
+
# * +subscribe+
|
35
|
+
# * +unsubscribe+
|
36
|
+
# * +upemail+
|
37
|
+
# * +profile+
|
38
|
+
#
|
39
|
+
# If a request comes in that does not match one of the four event types, it writes a warning to the default logger
|
40
|
+
#
|
41
|
+
# TODO: Write to a SubscribedTo specific log instead
|
42
|
+
def self.process(params)
|
43
|
+
type = params.delete("type").to_sym
|
44
|
+
hook = self.new(params)
|
45
|
+
|
46
|
+
hook.respond_to?(type) ?
|
47
|
+
hook.send(type.to_sym, params["data"]) :
|
48
|
+
Rails.logger.warn("WARNING: MailChimp WebHook does not support the #{type} event.")
|
49
|
+
rescue NoMethodError => e
|
50
|
+
Rails.logger.warn("WARNING: MailChimp WebHook: #{e.message}")
|
51
|
+
end
|
52
|
+
|
53
|
+
# Create a new instance and set some instance variables
|
54
|
+
def initialize(params) #:nodoc:
|
55
|
+
list_id = params["data"].delete("list_id")
|
56
|
+
self.enabled_models = SubscribedTo.mail_chimp_config.enabled_models[list_id]
|
57
|
+
end
|
58
|
+
|
59
|
+
# When a user registers on the site, they are automatically queued for inclusion on the mailing list (if they opt-in).
|
60
|
+
#
|
61
|
+
# After a user confirms their subscription (MailChimp recommends a double opt-in strategy, but it's not required),
|
62
|
+
# a webhook request is sent which includes the "web_id" - a unique ID for mail chimp users. We'll record this id
|
63
|
+
# to use with other updates.
|
64
|
+
def subscribe(params)
|
65
|
+
web_id = params["web_id"]
|
66
|
+
email = params["merges"]["EMAIL"]
|
67
|
+
|
68
|
+
subscriber = nil
|
69
|
+
enabled_models.each { |model| subscriber ||= model.constantize.find_by_email(email) }
|
70
|
+
|
71
|
+
subscriber.subscribed_to_list = true
|
72
|
+
subscriber.mail_chimp_id = web_id.to_i
|
73
|
+
subscriber.save_without_update_list_member(:validate => false)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Set the subscribed_to_list attribute to false to prevent any future MailChimp API calls when the user updates
|
77
|
+
# their profile in the web app.
|
78
|
+
def unsubscribe(params)
|
79
|
+
web_id = params["web_id"]
|
80
|
+
|
81
|
+
subscriber = nil
|
82
|
+
enabled_models.each { |model| subscriber ||= model.constantize.find_by_mail_chimp_id(web_id) }
|
83
|
+
|
84
|
+
subscriber.subscribed_to_list = false
|
85
|
+
subscriber.save_without_update_list_member(:validate => false)
|
86
|
+
end
|
87
|
+
|
88
|
+
# If a user updates their email from one of the MailChimp forms (they may get there from a link in an email, or from
|
89
|
+
# the confirm subscription page), then a webhook will be sent to the app with the a notice of the changed email.
|
90
|
+
# This method will update the web app users's email.
|
91
|
+
#
|
92
|
+
# Is this a good idea?
|
93
|
+
#
|
94
|
+
# Theoretically, it seems like the best idea is to keep the web app user and mailing list subscriber email
|
95
|
+
# addresses in sync.
|
96
|
+
#
|
97
|
+
# However, if the web app makes use of login by email, this could create confusion for the user. In this case,
|
98
|
+
# it may be best to send an email to the user notifying them that their login information has changed.
|
99
|
+
def upemail(params)
|
100
|
+
old_email = params["old_email"]
|
101
|
+
new_email = params["new_email"]
|
102
|
+
|
103
|
+
subscriber = nil
|
104
|
+
enabled_models.each { |model| subscriber ||= model.constantize.find_by_email(old_email) }
|
105
|
+
|
106
|
+
unless over_the_limit(subscriber.updated_at)
|
107
|
+
subscriber.email = new_email
|
108
|
+
subscriber.save_without_update_list_member(:validate => false)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# If a user updates any of their subscription information via a MailChimp web form, we need to update that info
|
113
|
+
# in the web app.
|
114
|
+
#
|
115
|
+
# We only update the attributes defined in the SubscribedTo.mail_chimp_config[:lists] merge vars. If more information
|
116
|
+
# is sent via the merge vars from MailChimp, but it is not defined in the mail_chimp_config, it is ignored.
|
117
|
+
def profile(params)
|
118
|
+
web_id = params["web_id"]
|
119
|
+
|
120
|
+
subscriber = nil
|
121
|
+
enabled_models.each { |model| subscriber ||= model.constantize.find_by_mail_chimp_id(web_id) }
|
122
|
+
|
123
|
+
unless over_the_limit(subscriber.updated_at)
|
124
|
+
subscriber.class.merge_vars.each { |key, method| subscriber.send("#{method.to_s}=", params["merges"][key]) unless params["merges"][key].blank? }
|
125
|
+
subscriber.save_without_update_list_member(:validate => false)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
def over_the_limit(updated_at)
|
132
|
+
(Time.zone.now - updated_at).seconds <= LIMIT
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'subscribed_to/mail_chimp/config'
|
2
|
+
require 'subscribed_to/mail_chimp/web_hook'
|
2
3
|
require 'hominid'
|
3
4
|
|
4
5
|
module SubscribedTo
|
@@ -13,7 +14,7 @@ module SubscribedTo
|
|
13
14
|
|
14
15
|
if subscribed_to_list
|
15
16
|
h = Hominid::API.new(SubscribedTo.mail_chimp_config.api_key)
|
16
|
-
h.list_subscribe(self.class.list_id, self.email, merge_vars.each { |key, method| merge_vars[key] = self.send(method.to_sym) })
|
17
|
+
h.list_subscribe(self.class.list_id, self.email, merge_vars.each { |key, method| merge_vars[key] = (self.send(method.to_sym) || "") })
|
17
18
|
end
|
18
19
|
rescue Hominid::APIError => e
|
19
20
|
Rails.logger.warn e
|
@@ -40,7 +41,7 @@ module SubscribedTo
|
|
40
41
|
h.list_subscribe(list_id, subscribed_email, merge_vars.each { |key, method| merge_vars[key] = self.send(method.to_sym) })
|
41
42
|
end
|
42
43
|
elsif subscribed_to_list && !(self.changed & merge_vars.collect { |key, method| method.to_s }).empty?
|
43
|
-
h.
|
44
|
+
h.list_update_member(list_id, subscribed_email, merge_vars.each { |key, method| merge_vars[key] = self.send(method.to_sym) })
|
44
45
|
end
|
45
46
|
end
|
46
47
|
rescue Hominid::APIError => e
|
data/lib/subscribed_to.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rails'
|
2
2
|
require 'active_record'
|
3
|
+
require 'active_record_extensions'
|
3
4
|
require 'subscribed_to/mail_chimp'
|
4
5
|
|
5
6
|
module SubscribedTo
|
@@ -26,6 +27,7 @@ module SubscribedTo
|
|
26
27
|
# config.mail_chimp do |mail_chimp_config|
|
27
28
|
# mail_chimp_config.api_key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-us1"
|
28
29
|
# mail_chimp_config.lists = {:mailing_list => {:id => "123456", :merge_vars => {"FNAME" => :first_name}
|
30
|
+
# mail_chimp_config.secret_key = "abc123"
|
29
31
|
# end
|
30
32
|
# end
|
31
33
|
def self.mail_chimp(&block)
|
@@ -47,6 +49,11 @@ module SubscribedTo
|
|
47
49
|
|
48
50
|
@list_key = id.to_sym
|
49
51
|
|
52
|
+
# We need to reference which models are enabled, and which list they belong to when processing the webhooks.
|
53
|
+
SubscribedTo.mail_chimp_config.enabled_models[self.list_id].blank? ?
|
54
|
+
SubscribedTo.mail_chimp_config.enabled_models[self.list_id] = [self.to_s] :
|
55
|
+
SubscribedTo.mail_chimp_config.enabled_models[self.list_id] << self.to_s
|
56
|
+
|
50
57
|
class_eval do
|
51
58
|
after_create :subscribe_to_list
|
52
59
|
after_update :update_list_member
|
@@ -79,3 +86,5 @@ module SubscribedTo
|
|
79
86
|
end
|
80
87
|
|
81
88
|
ActiveRecord::Base.send :include, SubscribedTo
|
89
|
+
|
90
|
+
require 'subscribed_to/engine'
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rspec/rails'
|
3
|
+
|
4
|
+
describe SubscribedTo::MailChimpWebHooksController do
|
5
|
+
include RSpec::Rails::ControllerExampleGroup
|
6
|
+
|
7
|
+
before do
|
8
|
+
SubscribedTo.mail_chimp do |config|
|
9
|
+
config.lists = {
|
10
|
+
:mailing_list => {
|
11
|
+
:id => "abc123",
|
12
|
+
:merge_vars => {"FNAME" => :first_name, "LNAME" => :last_name, "EMAIL" => :email}}}
|
13
|
+
|
14
|
+
# normally not set in config, but necessary for testing
|
15
|
+
config.enabled_models = {"abc123" => ["User"]}
|
16
|
+
|
17
|
+
config.secret_key = "abc123"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should respond with 404 to a request without a valid secret key" do
|
22
|
+
post :create
|
23
|
+
response.code.should eq "404"
|
24
|
+
|
25
|
+
post :create, { :key => "bad_key" }
|
26
|
+
response.code.should eq "404"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should respond with 200 to a request with a valid secret key" do
|
30
|
+
SubscribedTo::MailChimp::WebHook.stubs(:process).returns(true)
|
31
|
+
post :create, { :key => "abc123" }
|
32
|
+
response.code.should eq "200"
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should quietly fail and log the error if no member is found" do
|
36
|
+
Rails.logger.expects(:warn).once
|
37
|
+
expect do
|
38
|
+
post :create, {
|
39
|
+
"key" => "abc123",
|
40
|
+
"type" => "subscribe",
|
41
|
+
"data" => {
|
42
|
+
"list_id" => "abc123",
|
43
|
+
"web_id" => "231546749",
|
44
|
+
"merges" => {
|
45
|
+
"EMAIL" => "fake.user@email.com" }}}
|
46
|
+
end.not_to raise_exception
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should write a warning to the logger if the event is not supported" do
|
50
|
+
Rails.logger.expects(:warn).once
|
51
|
+
expect do
|
52
|
+
post :create, {
|
53
|
+
"key" => "abc123",
|
54
|
+
"type" => "nonevent",
|
55
|
+
"data" => { "list_id" => "abc123" }}
|
56
|
+
end.not_to raise_exception
|
57
|
+
end
|
58
|
+
|
59
|
+
context "for a new user" do
|
60
|
+
before(:each) do
|
61
|
+
@user = Factory.build(:non_subscribed_user)
|
62
|
+
@user.stubs(:subscribe_to_list)
|
63
|
+
@user.save
|
64
|
+
@user.expects(:update_list_member).never
|
65
|
+
end
|
66
|
+
|
67
|
+
context "when they subscribe" do
|
68
|
+
it "should set subscribed_to_list to true, and set the mail_chimp_id" do
|
69
|
+
@user.mail_chimp_id.should be_nil
|
70
|
+
expect do
|
71
|
+
expect do
|
72
|
+
post :create, {
|
73
|
+
"key" => "abc123",
|
74
|
+
"type" => "subscribe",
|
75
|
+
"data" => {
|
76
|
+
"list_id" => "abc123",
|
77
|
+
"web_id" => "231546749",
|
78
|
+
"merges" => {
|
79
|
+
"EMAIL" => @user.email }}}
|
80
|
+
end.to change { @user.reload.subscribed_to_list }.from(false).to(true)
|
81
|
+
end.to change { @user.mail_chimp_id }.to(231546749)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context "for an existing user" do
|
87
|
+
before(:each) do
|
88
|
+
# user was updated 2:01 ago
|
89
|
+
pretend_now_is(Time.zone.now - 121.seconds) do
|
90
|
+
@user = Factory.build(:subscribed_user)
|
91
|
+
@user.stubs(:subscribe_to_list)
|
92
|
+
@user.save
|
93
|
+
@user.expects(:update_list_member).never
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "when they unsubscribe" do
|
98
|
+
it "should set subscribed_to_list to false" do
|
99
|
+
expect do
|
100
|
+
post :create, {
|
101
|
+
"key" => "abc123",
|
102
|
+
"type" => "unsubscribe",
|
103
|
+
"data" => {
|
104
|
+
"list_id" => "abc123",
|
105
|
+
"web_id" => "123",
|
106
|
+
"merges" => {
|
107
|
+
"EMAIL" => @user.email }}}
|
108
|
+
end.to change { @user.reload.subscribed_to_list }.from(true).to(false)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context "when they change their email" do
|
113
|
+
it "should update the user email" do
|
114
|
+
expect do
|
115
|
+
post :create, {
|
116
|
+
"key" => "abc123",
|
117
|
+
"type" => "upemail",
|
118
|
+
"data" => {
|
119
|
+
"list_id" => "abc123",
|
120
|
+
"new_email" => "my.new@email.com",
|
121
|
+
"old_email" => @user.email }}
|
122
|
+
end.to change { @user.reload.email }.to("my.new@email.com")
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
context "when they change their profile information" do
|
127
|
+
it "should update the attributes defined in the merge vars config" do
|
128
|
+
expect do
|
129
|
+
expect do
|
130
|
+
expect do
|
131
|
+
post :create, {
|
132
|
+
"key" => "abc123",
|
133
|
+
"type" => "profile",
|
134
|
+
"data" => {
|
135
|
+
"list_id" => "abc123",
|
136
|
+
"web_id" => "123",
|
137
|
+
"merges" => {
|
138
|
+
"EMAIL" => "my.new@email.com",
|
139
|
+
"FNAME" => "John",
|
140
|
+
"LNAME" => "Locke" }}}
|
141
|
+
end.to change { @user.reload.email }.to("my.new@email.com")
|
142
|
+
end.to change { @user.first_name }.to("John")
|
143
|
+
end.to change { @user.last_name }.to("Locke")
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
data/spec/dummy/Rakefile
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
2
|
+
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
3
|
+
|
4
|
+
require File.expand_path('../config/application', __FILE__)
|
5
|
+
require 'rake'
|
6
|
+
|
7
|
+
Dummy::Application.load_tasks
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require File.expand_path('../boot', __FILE__)
|
2
|
+
|
3
|
+
require "active_model/railtie"
|
4
|
+
require "active_record/railtie"
|
5
|
+
require "action_controller/railtie"
|
6
|
+
require "action_view/railtie"
|
7
|
+
require "action_mailer/railtie"
|
8
|
+
|
9
|
+
Bundler.require
|
10
|
+
require "subscribed_to"
|
11
|
+
|
12
|
+
module Dummy
|
13
|
+
class Application < Rails::Application
|
14
|
+
# Settings in config/environments/* take precedence over those specified here.
|
15
|
+
# Application configuration should go into files in config/initializers
|
16
|
+
# -- all .rb files in that directory are automatically loaded.
|
17
|
+
|
18
|
+
# Custom directories with classes and modules you want to be autoloadable.
|
19
|
+
# config.autoload_paths += %W(#{config.root}/extras)
|
20
|
+
|
21
|
+
# Only load the plugins named here, in the order given (default is alphabetical).
|
22
|
+
# :all can be used as a placeholder for all plugins not explicitly named.
|
23
|
+
# config.plugins = [ :exception_notification, :ssl_requirement, :all ]
|
24
|
+
|
25
|
+
# Activate observers that should always be running.
|
26
|
+
# config.active_record.observers = :cacher, :garbage_collector, :forum_observer
|
27
|
+
|
28
|
+
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
|
29
|
+
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
|
30
|
+
# config.time_zone = 'Central Time (US & Canada)'
|
31
|
+
|
32
|
+
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
33
|
+
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
34
|
+
# config.i18n.default_locale = :de
|
35
|
+
|
36
|
+
# JavaScript files you want as :defaults (application.js is always included).
|
37
|
+
# config.action_view.javascript_expansions[:defaults] = %w(jquery rails)
|
38
|
+
|
39
|
+
# Configure the default encoding used in templates for Ruby 1.9.
|
40
|
+
config.encoding = "utf-8"
|
41
|
+
|
42
|
+
# Configure sensitive parameters which will be filtered from the log file.
|
43
|
+
config.filter_parameters += [:password]
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# SQLite version 3.x
|
2
|
+
# gem install sqlite3
|
3
|
+
development:
|
4
|
+
adapter: sqlite3
|
5
|
+
database: db/development.sqlite3
|
6
|
+
pool: 5
|
7
|
+
timeout: 5000
|
8
|
+
|
9
|
+
# Warning: The database defined as "test" will be erased and
|
10
|
+
# re-generated from your development database when you run "rake".
|
11
|
+
# Do not set this db to the same as development or production.
|
12
|
+
test:
|
13
|
+
adapter: sqlite3
|
14
|
+
database: db/test.sqlite3
|
15
|
+
pool: 5
|
16
|
+
timeout: 5000
|
17
|
+
|
18
|
+
production:
|
19
|
+
adapter: sqlite3
|
20
|
+
database: db/production.sqlite3
|
21
|
+
pool: 5
|
22
|
+
timeout: 5000
|
@@ -0,0 +1,26 @@
|
|
1
|
+
Dummy::Application.configure do
|
2
|
+
# Settings specified here will take precedence over those in config/application.rb
|
3
|
+
|
4
|
+
# In the development environment your application's code is reloaded on
|
5
|
+
# every request. This slows down response time but is perfect for development
|
6
|
+
# since you don't have to restart the webserver when you make code changes.
|
7
|
+
config.cache_classes = false
|
8
|
+
|
9
|
+
# Log error messages when you accidentally call methods on nil.
|
10
|
+
config.whiny_nils = true
|
11
|
+
|
12
|
+
# Show full error reports and disable caching
|
13
|
+
config.consider_all_requests_local = true
|
14
|
+
config.action_view.debug_rjs = true
|
15
|
+
config.action_controller.perform_caching = false
|
16
|
+
|
17
|
+
# Don't care if the mailer can't send
|
18
|
+
config.action_mailer.raise_delivery_errors = false
|
19
|
+
|
20
|
+
# Print deprecation notices to the Rails logger
|
21
|
+
config.active_support.deprecation = :log
|
22
|
+
|
23
|
+
# Only use best-standards-support built into browsers
|
24
|
+
config.action_dispatch.best_standards_support = :builtin
|
25
|
+
end
|
26
|
+
|