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.
Files changed (63) hide show
  1. data/Gemfile +1 -0
  2. data/Gemfile.lock +2 -0
  3. data/README.rdoc +32 -0
  4. data/app/controllers/subscribed_to/mail_chimp_web_hooks_controller.rb +19 -0
  5. data/config/routes.rb +5 -0
  6. data/lib/active_record_extensions.rb +10 -0
  7. data/lib/generators/subscribed_to/templates/migration.rb +8 -0
  8. data/lib/generators/subscribed_to/templates/subscribed_to.rb +4 -0
  9. data/lib/subscribed_to/engine.rb +7 -0
  10. data/lib/subscribed_to/mail_chimp/config.rb +5 -3
  11. data/lib/subscribed_to/mail_chimp/web_hook.rb +136 -0
  12. data/lib/subscribed_to/mail_chimp.rb +3 -2
  13. data/lib/subscribed_to/version.rb +1 -1
  14. data/lib/subscribed_to.rb +9 -0
  15. data/spec/app/controllers/subscribed_to/mail_chimp_web_hooks_spec.rb +147 -0
  16. data/spec/dummy/Rakefile +7 -0
  17. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  18. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  19. data/spec/dummy/app/models/user.rb +3 -0
  20. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  21. data/spec/dummy/config/application.rb +45 -0
  22. data/spec/dummy/config/boot.rb +10 -0
  23. data/spec/dummy/config/database.yml +22 -0
  24. data/spec/dummy/config/environment.rb +5 -0
  25. data/spec/dummy/config/environments/development.rb +26 -0
  26. data/spec/dummy/config/environments/production.rb +49 -0
  27. data/spec/dummy/config/environments/test.rb +35 -0
  28. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  29. data/spec/dummy/config/initializers/inflections.rb +10 -0
  30. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  31. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  32. data/spec/dummy/config/initializers/session_store.rb +8 -0
  33. data/spec/dummy/config/initializers/subscribed_to.rb +21 -0
  34. data/spec/dummy/config/locales/en.yml +5 -0
  35. data/spec/dummy/config/routes.rb +2 -0
  36. data/spec/dummy/config.ru +4 -0
  37. data/spec/dummy/db/migrate/1_create_users.rb +18 -0
  38. data/spec/dummy/db/schema.rb +26 -0
  39. data/spec/dummy/public/404.html +26 -0
  40. data/spec/dummy/public/422.html +26 -0
  41. data/spec/dummy/public/500.html +26 -0
  42. data/spec/dummy/public/favicon.ico +0 -0
  43. data/spec/dummy/public/javascripts/application.js +2 -0
  44. data/spec/dummy/public/javascripts/controls.js +965 -0
  45. data/spec/dummy/public/javascripts/dragdrop.js +974 -0
  46. data/spec/dummy/public/javascripts/effects.js +1123 -0
  47. data/spec/dummy/public/javascripts/prototype.js +6001 -0
  48. data/spec/dummy/public/javascripts/rails.js +191 -0
  49. data/spec/dummy/public/stylesheets/.gitkeep +0 -0
  50. data/spec/dummy/script/rails +6 -0
  51. data/spec/factories/users.rb +1 -0
  52. data/spec/{generators → lib/generators}/install_generator_spec.rb +0 -0
  53. data/spec/{subscribed_to → lib/subscribed_to}/mail_chimp/config_spec.rb +0 -0
  54. data/spec/lib/subscribed_to/mail_chimp/web_hook_spec.rb +158 -0
  55. data/spec/lib/subscribed_to/mail_chimp_spec.rb +74 -0
  56. data/spec/{subscribed_to_spec.rb → lib/subscribed_to_spec.rb} +0 -0
  57. data/spec/spec_helper.rb +70 -28
  58. data/subscribed_to.gemspec +136 -0
  59. metadata +77 -26
  60. data/spec/app/models/user.rb +0 -43
  61. data/spec/database.yml.example +0 -17
  62. data/spec/schema.rb +0 -9
  63. 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,5 @@
1
+ Rails.application.routes.draw do
2
+ namespace :subscribed_to do
3
+ match "mail_chimp" => "mail_chimp_web_hooks#create", :via => :post
4
+ end
5
+ end
@@ -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
@@ -0,0 +1,7 @@
1
+ require "subscribed_to"
2
+ require "rails"
3
+
4
+ module SubscribedTo
5
+ class Engine < Rails::Engine #:nodoc:
6
+ end
7
+ 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] ||= nil
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.listUpdateMember(list_id, subscribed_email, merge_vars.each { |key, method| merge_vars[key] = self.send(method.to_sym) })
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
@@ -1,7 +1,7 @@
1
1
  module SubscribedTo
2
2
  module Version #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 2
4
+ MINOR = 3
5
5
  PATCH = 0
6
6
  BUILD = nil
7
7
 
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
@@ -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,3 @@
1
+ class ApplicationController < ActionController::Base
2
+ protect_from_forgery
3
+ end
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end
@@ -0,0 +1,3 @@
1
+ class User < ActiveRecord::Base
2
+ subscribed_to :mailing_list
3
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Dummy</title>
5
+ <%= stylesheet_link_tag :all %>
6
+ <%= javascript_include_tag :defaults %>
7
+ <%= csrf_meta_tag %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
@@ -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,10 @@
1
+ require 'rubygems'
2
+ gemfile = File.expand_path('../../../../Gemfile', __FILE__)
3
+
4
+ if File.exist?(gemfile)
5
+ ENV['BUNDLE_GEMFILE'] = gemfile
6
+ require 'bundler'
7
+ Bundler.setup
8
+ end
9
+
10
+ $:.unshift File.expand_path('../../../../lib', __FILE__)
@@ -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,5 @@
1
+ # Load the rails application
2
+ require File.expand_path('../application', __FILE__)
3
+
4
+ # Initialize the rails application
5
+ Dummy::Application.initialize!
@@ -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
+