gogogibbon 2.0.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.
- checksums.yaml +7 -0
- data/gogogibbon.gemspec +15 -0
- data/lib/gogogibbon/callbacks.rb +42 -0
- data/lib/gogogibbon/commands.rb +173 -0
- data/lib/gogogibbon/config.rb +28 -0
- data/lib/gogogibbon/methods.rb +48 -0
- data/lib/gogogibbon/version.rb +3 -0
- data/lib/gogogibbon.rb +59 -0
- metadata +63 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 67f93827920932b5384a0fd9554480650fcdeed698343cb2c022140992276f9d
|
4
|
+
data.tar.gz: 451d17a1a97d08e88fc44dd6c8f69edf9d9a372c322e536a3edf2501b05fe66b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6be359084aa1139bcc02d071bf68017a50132dfc025e054abda77cca37558c56b401c3a7ee9043c48e257225b7c22134b7de8811aa4c4ea0d60ebe62d7125ba7
|
7
|
+
data.tar.gz: f4465841d537ac0b149f4e7bc3dc18e58ec1486b6b31317d69e8d4db67fe1d62af11b649c7eadf1442cd64d15b45bb994645438c481940a7233c802483043981
|
data/gogogibbon.gemspec
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.expand_path('../lib/gogogibbon/version', __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'gogogibbon'
|
5
|
+
s.version = GoGoGibbon::VERSION
|
6
|
+
s.summary = 'Useful helpers for Gibbon'
|
7
|
+
s.description = 'A wrapper for Gibbon containing useful helper methods.'
|
8
|
+
s.authors = ['GoGoCarl']
|
9
|
+
s.email = 'carl.scott@solertium.com'
|
10
|
+
s.files = Dir['lib/**/*'] + Dir['*.rb'] + ["gogogibbon.gemspec"]
|
11
|
+
s.require_paths = ["lib"]
|
12
|
+
s.homepage = 'http://github.com/GoGoCarl/gogogibbon'
|
13
|
+
|
14
|
+
s.add_dependency 'gibbon', '~> 2.2'
|
15
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module GoGoGibbon
|
2
|
+
|
3
|
+
class Callbacks
|
4
|
+
|
5
|
+
def initialize opts={}
|
6
|
+
@options = { :thread => false }
|
7
|
+
@options.merge! opts
|
8
|
+
end
|
9
|
+
|
10
|
+
def after_create record
|
11
|
+
run do
|
12
|
+
GoGoGibbon.subscribe record
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def after_update record
|
17
|
+
if record.email_changed? || record.first_name_changed? || record.last_name_changed?
|
18
|
+
run do
|
19
|
+
GoGoGibbon.update_subscription record.email_was, record
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def after_destroy record
|
25
|
+
run do
|
26
|
+
GoGoGibbon.cancel_user record
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def run &block
|
31
|
+
if @options[:thread] == true
|
32
|
+
Thread.new do
|
33
|
+
yield
|
34
|
+
end
|
35
|
+
else
|
36
|
+
yield
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
require 'gibbon'
|
2
|
+
|
3
|
+
module GoGoGibbon
|
4
|
+
module Commands
|
5
|
+
class << self
|
6
|
+
# Store a hash of list name to ID
|
7
|
+
LIST_CACHE = {}
|
8
|
+
|
9
|
+
#
|
10
|
+
# Subscribe to the subscription list
|
11
|
+
#
|
12
|
+
def subscribe user, list_name=sub_list
|
13
|
+
result = false
|
14
|
+
sub_id = list list_name
|
15
|
+
unless sub_id.nil?
|
16
|
+
begin
|
17
|
+
body = {
|
18
|
+
'email_address' => user.email,
|
19
|
+
'status' => 'subscribed',
|
20
|
+
'merge_fields' => { 'FNAME' => user.first_name, 'LNAME' => user.last_name }
|
21
|
+
}
|
22
|
+
result = chimp.lists(sub_id).members.create(body: body)
|
23
|
+
rescue Gibbon::MailChimpError => e
|
24
|
+
raise e unless e.body['status'] == 400 && e.body['title'] == 'Member Exists'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
result
|
28
|
+
end
|
29
|
+
|
30
|
+
def subscribe_set users, list_name=sub_list
|
31
|
+
result = false
|
32
|
+
|
33
|
+
sub_id = list list_name
|
34
|
+
unless sub_id.nil?
|
35
|
+
batch = []
|
36
|
+
|
37
|
+
defaults = { 'method' => 'POST', 'path' => "lists/#{sub_id}/members" }
|
38
|
+
handler = lambda do |user|
|
39
|
+
batch << defaults.merge("body" => {
|
40
|
+
'email_address' => user.email, 'status' => 'subscribed',
|
41
|
+
'merge_fields' => { 'FNAME' => user.first_name, 'LNAME' => user.last_name }
|
42
|
+
}.to_json)
|
43
|
+
end
|
44
|
+
|
45
|
+
if users.respond_to? :find_each
|
46
|
+
users.find_each { |user| handler.call(user) }
|
47
|
+
else
|
48
|
+
users.each { |user| handler.call(user) }
|
49
|
+
end
|
50
|
+
|
51
|
+
body = { "operations" => batch }
|
52
|
+
|
53
|
+
result = chimp.batches.create(body: body)
|
54
|
+
batch_id = result['id']
|
55
|
+
attempts = 1, backoff = 2
|
56
|
+
while result['status'] != 'finished' && attempts <= 10
|
57
|
+
sleep attempts * backoff
|
58
|
+
result = chimp.batches(batch_id).retrieve
|
59
|
+
attempts += 1
|
60
|
+
end
|
61
|
+
|
62
|
+
if result['status'] == 'finished'
|
63
|
+
result = {
|
64
|
+
'add_count' => result['finished_operations'],
|
65
|
+
'update_count' => 0,
|
66
|
+
'error_count' => result['errored_operations'],
|
67
|
+
'total_count' => result['total_operations'],
|
68
|
+
'errors' => []
|
69
|
+
}
|
70
|
+
|
71
|
+
else
|
72
|
+
result = false
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
result
|
77
|
+
end
|
78
|
+
|
79
|
+
def unsubscribe user, list_name=unsub_list
|
80
|
+
result = false
|
81
|
+
|
82
|
+
sub_id = list list_name
|
83
|
+
unless sub_id.nil?
|
84
|
+
begin
|
85
|
+
result = chimp.lists(sub_id).members(user_id(user.email)).delete
|
86
|
+
rescue Gibbon::MailChimpError => e
|
87
|
+
if e.body['status'] == 404
|
88
|
+
return true
|
89
|
+
else
|
90
|
+
raise e
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
result.nil?
|
95
|
+
end
|
96
|
+
|
97
|
+
#
|
98
|
+
# Unsubscribe from the subscription list,
|
99
|
+
# subscribe to the unsubscription list.
|
100
|
+
#
|
101
|
+
def cancel_user user
|
102
|
+
result = false
|
103
|
+
unsubscribe user, sub_list
|
104
|
+
result = subscribe user, unsub_list
|
105
|
+
result
|
106
|
+
end
|
107
|
+
|
108
|
+
def list list_name
|
109
|
+
return LIST_CACHE[list_name] if LIST_CACHE.key?(list_name)
|
110
|
+
items = lists
|
111
|
+
list = nil
|
112
|
+
if items
|
113
|
+
p = items.select { |i| i['name'] == list_name }
|
114
|
+
if p.any?
|
115
|
+
list = p.first['id']
|
116
|
+
end
|
117
|
+
end
|
118
|
+
list
|
119
|
+
end
|
120
|
+
|
121
|
+
def update_subscription old_email, user, list_name=sub_list
|
122
|
+
result = false
|
123
|
+
|
124
|
+
sub_id = list list_name
|
125
|
+
unless sub_id.nil?
|
126
|
+
if old_email != user.email
|
127
|
+
unsubscribe Struct.new(:email).new(old_email), list_name
|
128
|
+
end
|
129
|
+
|
130
|
+
body = {
|
131
|
+
'email_address' => user.email, 'status' => 'subscribed',
|
132
|
+
'merge_fields' => { 'FNAME' => user.first_name, 'LNAME' => user.last_name }
|
133
|
+
}
|
134
|
+
|
135
|
+
result = chimp.lists(sub_id).members(user_id(user.email)).upsert(body: body)
|
136
|
+
end
|
137
|
+
result
|
138
|
+
end
|
139
|
+
|
140
|
+
def lists
|
141
|
+
result = nil
|
142
|
+
begin
|
143
|
+
result = chimp.lists.retrieve(params: { "count" => 100, "fields" => "lists.id,lists.name" })["lists"]
|
144
|
+
result.each do |item|
|
145
|
+
LIST_CACHE[item['name']] = item['id']
|
146
|
+
end
|
147
|
+
rescue Gibbon::MailChimpError => e
|
148
|
+
puts e.detail
|
149
|
+
raise e unless e.body['status'] == 200
|
150
|
+
end
|
151
|
+
result
|
152
|
+
end
|
153
|
+
|
154
|
+
def chimp
|
155
|
+
GoGoGibbon::Config.chimp
|
156
|
+
end
|
157
|
+
|
158
|
+
def sub_list
|
159
|
+
GoGoGibbon::Config.subscribed
|
160
|
+
end
|
161
|
+
|
162
|
+
def unsub_list
|
163
|
+
GoGoGibbon::Config.unsubscribed
|
164
|
+
end
|
165
|
+
|
166
|
+
private
|
167
|
+
|
168
|
+
def user_id email
|
169
|
+
Digest::MD5.new.update(email.downcase).hexdigest
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'gibbon'
|
2
|
+
|
3
|
+
module GoGoGibbon
|
4
|
+
class Config
|
5
|
+
class << self
|
6
|
+
|
7
|
+
attr_accessor :subscribed, :unsubscribed, :api_key, :chimp, :errors, :on_fail
|
8
|
+
|
9
|
+
def api_key=(value)
|
10
|
+
@chimp = Gibbon::Request.new api_key: value
|
11
|
+
@api_key = value
|
12
|
+
end
|
13
|
+
|
14
|
+
def configured?
|
15
|
+
!(@api_key.nil? || @subscribed.nil?)
|
16
|
+
end
|
17
|
+
|
18
|
+
def fail!
|
19
|
+
msg = 'MailChimp Configuration not complete. Please specify an api_key and subscription list.'
|
20
|
+
if @on_fail == :error
|
21
|
+
raise Exception.new msg
|
22
|
+
else
|
23
|
+
puts msg unless @on_fail == :silent
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module GoGoGibbon
|
2
|
+
module Methods
|
3
|
+
|
4
|
+
def self.included base
|
5
|
+
base.send :extend, ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
#
|
10
|
+
# Options map can contain the following:
|
11
|
+
# * :thread -- true to run in a new thread, false otherwise (default false)
|
12
|
+
#
|
13
|
+
|
14
|
+
#
|
15
|
+
# When a user is created, subscribe that user to the mailing list
|
16
|
+
#
|
17
|
+
def mailchimp_on_create opts={}
|
18
|
+
after_create GoGoGibbon::Callbacks.new opts
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# When a user is updated, update their profile, if necessary
|
23
|
+
#
|
24
|
+
def mailchimp_on_update opts={}
|
25
|
+
after_update GoGoGibbon::Callbacks.new opts
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# When a user is deleted, cancel that user.
|
30
|
+
#
|
31
|
+
def mailchimp_on_destroy opts={}
|
32
|
+
after_destroy GoGoGibbon::Callbacks.new opts
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
# Return a list of users eligible to receive mail. Defaults to this class,
|
37
|
+
# but can return anything relation
|
38
|
+
#
|
39
|
+
def Mailable
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
ActiveRecord::Base.send :include, GoGoGibbon::Methods
|
data/lib/gogogibbon.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'gogogibbon/commands'
|
2
|
+
require 'gogogibbon/config'
|
3
|
+
require 'gogogibbon/version'
|
4
|
+
require 'gogogibbon/callbacks'
|
5
|
+
require 'gogogibbon/methods'
|
6
|
+
|
7
|
+
module GoGoGibbon
|
8
|
+
class << self
|
9
|
+
|
10
|
+
#
|
11
|
+
# Add a new user to the MailChimp subscription list
|
12
|
+
#
|
13
|
+
def subscribe user
|
14
|
+
execute { GoGoGibbon::Commands.subscribe user }
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
# Remove the user from the MailChimp subscription list. If there is
|
19
|
+
# a cancellation list configured, they will be subscribed to that.
|
20
|
+
#
|
21
|
+
def cancel_user user
|
22
|
+
execute { GoGoGibbon::Commands.cancel_user user }
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# Update a user subscription given a user with the properties
|
27
|
+
# email, first_name, and last_name. You can always pass a struct
|
28
|
+
# with these properties if your user object has these fields named
|
29
|
+
# differently.
|
30
|
+
#
|
31
|
+
def update_subscription old_email, user
|
32
|
+
execute { GoGoGibbon::Commands.update_subscription old_email, user }
|
33
|
+
end
|
34
|
+
|
35
|
+
def execute &block
|
36
|
+
return unless ready?
|
37
|
+
yield
|
38
|
+
rescue Exception => e
|
39
|
+
if GoGoGibbon::Config.errors = :throw
|
40
|
+
raise e
|
41
|
+
else
|
42
|
+
return false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# Returns true if Gibbon has enough information to run, false otherwise.
|
48
|
+
# API Key and subscription list are minimally required.
|
49
|
+
#
|
50
|
+
def ready?
|
51
|
+
result = GoGoGibbon::Config.configured?
|
52
|
+
unless result
|
53
|
+
GoGoGibbon::Config.fail!
|
54
|
+
end
|
55
|
+
result
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gogogibbon
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- GoGoCarl
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-03-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: gibbon
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.2'
|
27
|
+
description: A wrapper for Gibbon containing useful helper methods.
|
28
|
+
email: carl.scott@solertium.com
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- gogogibbon.gemspec
|
34
|
+
- lib/gogogibbon.rb
|
35
|
+
- lib/gogogibbon/callbacks.rb
|
36
|
+
- lib/gogogibbon/commands.rb
|
37
|
+
- lib/gogogibbon/config.rb
|
38
|
+
- lib/gogogibbon/methods.rb
|
39
|
+
- lib/gogogibbon/version.rb
|
40
|
+
homepage: http://github.com/GoGoCarl/gogogibbon
|
41
|
+
licenses: []
|
42
|
+
metadata: {}
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
requirements: []
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 2.7.6
|
60
|
+
signing_key:
|
61
|
+
specification_version: 4
|
62
|
+
summary: Useful helpers for Gibbon
|
63
|
+
test_files: []
|