effective_mailchimp 0.7.0 → 0.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d3b3306349bc71e4dcd895a1be96411b94e82c76155972d5ee73ad302487fa5d
4
- data.tar.gz: 590439bc94cc48d34586b14eeba77476e5fc715ee32118a973c640fdc25e6def
3
+ metadata.gz: 56caa6a3804ed54f997cb2a732022cb077c37ec186f2a42476b2433b59f80bab
4
+ data.tar.gz: 51a5b095d91881d957c227c6f13155d78d3a9178aa3703982cf2fd4b8d92cd37
5
5
  SHA512:
6
- metadata.gz: 59eab329289651cd579828198bafbad8093aa94e452866f6dc2a51b5a787a7b077e57d644e5caa7cf91b868d12db82bdb28284680e7a3608f216c7bbbd4e73ad
7
- data.tar.gz: fc0bbcadfffd0caae215be540ad150bf588264ae7ee013b4a4cbe8d0ea7064fe603d4f9bd4abfe70c6ef341d931d5e1ec1bed60f15735f5603f777e54c827d1a
6
+ metadata.gz: 246b57c7659cbb154db572309d4a886132cef6cdf9d1bd09e4cafd37fd15dfc2d109375a2c179173bf710c478fb71306b1dc69a0c57587a6d66c4286edf6b446
7
+ data.tar.gz: 578e421f5e538bc705fcc0a4ab8290cd0adc4fae51388ddf941f934bbd4ea2c069eb13530d96c789ed4c8110d2e4ca5960a8274a1ae154e58cc30971a8722f3f
@@ -16,9 +16,7 @@ module Admin
16
16
  EffectiveResources.authorize!(self, :admin, :mailchimp_sync)
17
17
 
18
18
  api = EffectiveMailchimp.api
19
- merge_fields = current_user.class.new().mailchimp_merge_fields
20
-
21
- Effective::MailchimpList.sync!(api: api, merge_fields: merge_fields)
19
+ Effective::MailchimpList.sync!(api: api)
22
20
  Effective::MailchimpCategory.sync!(api: api)
23
21
  Effective::MailchimpInterest.sync!(api: api)
24
22
 
@@ -31,6 +31,10 @@ module Admin
31
31
  ml.merge_fields.join(', ')
32
32
  end
33
33
 
34
+ col :member_count do |list|
35
+ list.member_count.to_i
36
+ end
37
+
34
38
  actions_col
35
39
  end
36
40
 
@@ -0,0 +1,8 @@
1
+ class EffectiveMailchimpSubscribeAllMembersJob < ApplicationJob
2
+
3
+ def perform(mailchimp_list)
4
+ raise('expected an Effective::MailchimpList') unless mailchimp_list.kind_of?(Effective::MailchimpList)
5
+ mailchimp_list.subscribe_all_members!(now: true)
6
+ end
7
+
8
+ end
@@ -0,0 +1,8 @@
1
+ class EffectiveMailchimpSubscribeAllUsersJob < ApplicationJob
2
+
3
+ def perform(mailchimp_list)
4
+ raise('expected an Effective::MailchimpList') unless mailchimp_list.kind_of?(Effective::MailchimpList)
5
+ mailchimp_list.subscribe_all_users!(now: true)
6
+ end
7
+
8
+ end
@@ -59,12 +59,13 @@ module EffectiveMailchimpUser
59
59
  member.assign_attributes(subscribed: subscribed)
60
60
  end
61
61
 
62
- # This sets up the after_commit to run the mailchimp_update! job
63
- assign_attributes(mailchimp_user_form_action: true)
64
-
65
62
  # For use in a rake task. Run the update right now
66
- mailchimp_update! if now
63
+ if now
64
+ return mailchimp_update!(only: mailchimp_lists)
65
+ end
67
66
 
67
+ # This sets up the after_commit to run the mailchimp_update! job
68
+ assign_attributes(mailchimp_user_form_action: true)
68
69
  save!
69
70
  end
70
71
 
@@ -173,8 +174,7 @@ module EffectiveMailchimpUser
173
174
  # Pulls the current status from Mailchimp API into the Mailchimp List Member objects
174
175
  # Run before the mailchimp fields are displayed
175
176
  # Only run in the background when a user or admin clicks sync now
176
- def mailchimp_sync!
177
- api = EffectiveMailchimp.api
177
+ def mailchimp_sync!(api: EffectiveMailchimp.api)
178
178
  lists = Effective::MailchimpList.subscribable.sorted.to_a
179
179
 
180
180
  assign_attributes(mailchimp_user_form_action: nil)
@@ -198,12 +198,13 @@ module EffectiveMailchimpUser
198
198
 
199
199
  # Pushes the current Mailchimp List Member objects to Mailchimp when needed
200
200
  # Called in the background after a form submission that changes the user email/last_name/first_name or mailchimp subscriptions
201
- def mailchimp_update!
202
- api = EffectiveMailchimp.api
203
-
201
+ def mailchimp_update!(api: EffectiveMailchimp.api, only: [], except: [])
204
202
  assign_attributes(mailchimp_user_form_action: nil)
205
203
 
206
204
  mailchimp_list_members.each do |member|
205
+ next if only.present? && Array(only).exclude?(member.mailchimp_list)
206
+ next if except.present? && Array(except).include?(member.mailchimp_list)
207
+
207
208
  begin
208
209
  list_member = if member.mailchimp_id.blank? && member.subscribed?
209
210
  api.list_member_add(member)
@@ -25,6 +25,10 @@ module Effective
25
25
  Rails.env.development?
26
26
  end
27
27
 
28
+ def sandbox_mode?
29
+ EffectiveMailchimp.sandbox_mode?
30
+ end
31
+
28
32
  def admin_url
29
33
  "https://#{server}.admin.mailchimp.com"
30
34
  end
@@ -56,27 +60,27 @@ module Effective
56
60
  # Returns an Array of Lists, which are each Hash
57
61
  # Like this [{ ...}, { ... }]
58
62
  def lists
59
- Rails.logger.info "[effective_mailchimp] Index Lists..." if debug?
63
+ Rails.logger.info "[effective_mailchimp] Index Lists" if debug?
60
64
 
61
65
  response = client.lists.get_all_lists(count: 250)
62
66
  Array(response['lists']) - [nil, '', {}]
63
67
  end
64
68
 
65
69
  def list(id)
66
- Rails.logger.info "[effective_mailchimp] Show List..." if debug?
70
+ Rails.logger.info "[effective_mailchimp] Get List" if debug?
67
71
 
68
72
  client.lists.get_list(id.try(:mailchimp_id) || id)
69
73
  end
70
74
 
71
75
  def categories(list_id)
72
- Rails.logger.info "[effective_mailchimp] Index Interest Categories..." if debug?
76
+ Rails.logger.info "[effective_mailchimp] Index Interest Categories" if debug?
73
77
 
74
78
  response = client.lists.get_list_interest_categories(list_id.try(:mailchimp_id) || list_id)
75
79
  Array(response['categories']) - [nil, '', {}]
76
80
  end
77
81
 
78
82
  def interests(list_id, category_id)
79
- Rails.logger.info "[effective_mailchimp] Index Interest Category Interests..." if debug?
83
+ Rails.logger.info "[effective_mailchimp] Index Interest Category Interests" if debug?
80
84
 
81
85
  response = client.lists.list_interest_category_interests(list_id, category_id)
82
86
  Array(response['interests']) - [nil, '', {}]
@@ -85,6 +89,8 @@ module Effective
85
89
  def list_member(id, email)
86
90
  raise('expected an email') unless email.to_s.include?('@')
87
91
 
92
+ Rails.logger.info "[effective_mailchimp] Get List Member" if debug?
93
+
88
94
  begin
89
95
  client.lists.get_list_member(id.try(:mailchimp_id) || id, email)
90
96
  rescue MailchimpMarketing::ApiError => e
@@ -93,18 +99,24 @@ module Effective
93
99
  end
94
100
 
95
101
  def list_merge_fields(id)
102
+ Rails.logger.info "[effective_mailchimp] Get List Merge Fields" if debug?
103
+
96
104
  response = client.lists.get_list_merge_fields(id.try(:mailchimp_id) || id, count: 100)
97
- Array(response['merge_fields']) - [nil, '', {}]
105
+ Array(response['merge_fields']) - [nil, '', ' ', {}]
98
106
  end
99
107
 
100
108
  def add_merge_field(id, name:, type: :text)
101
109
  raise("invalid mailchimp merge key: #{name}. Must be 10 or fewer characters") if name.to_s.length > 10
102
110
 
111
+ return if sandbox_mode?
112
+ Rails.logger.info "[effective_mailchimp] Add List Merge Field #{name}" if debug?
113
+
103
114
  payload = { name: name.to_s.titleize, tag: name.to_s, type: type }
104
115
 
105
116
  begin
106
117
  client.lists.add_list_merge_field(id.try(:mailchimp_id) || id, payload)
107
118
  rescue MailchimpMarketing::ApiError => e
119
+ EffectiveLogger.error(e.message, details: name.to_s) if defined?(EffectiveLogger)
108
120
  false
109
121
  end
110
122
  end
@@ -112,9 +124,18 @@ module Effective
112
124
  def list_member_add(member)
113
125
  raise('expected an Effective::MailchimpListMember') unless member.kind_of?(Effective::MailchimpListMember)
114
126
 
127
+ return if sandbox_mode?
128
+ Rails.logger.info "[effective_mailchimp] Add List Member" if debug?
129
+
130
+ # See if they exist somehow
115
131
  existing = list_member(member.mailchimp_list, member.user.email)
116
- return existing if existing.present?
117
132
 
133
+ if existing.present?
134
+ member.assign_attributes(mailchimp_id: existing['id'])
135
+ return list_member_update(member)
136
+ end
137
+
138
+ # Actually add
118
139
  payload = list_member_payload(member)
119
140
  client.lists.add_list_member(member.mailchimp_list.mailchimp_id, payload)
120
141
  end
@@ -122,6 +143,9 @@ module Effective
122
143
  def list_member_update(member)
123
144
  raise('expected an Effective::MailchimpListMember') unless member.kind_of?(Effective::MailchimpListMember)
124
145
 
146
+ return if sandbox_mode?
147
+ Rails.logger.info "[effective_mailchimp] Update List Member" if debug?
148
+
125
149
  payload = list_member_payload(member)
126
150
  client.lists.update_list_member(member.mailchimp_list.mailchimp_id, member.email, payload)
127
151
  end
@@ -25,7 +25,8 @@ module Effective
25
25
  scope :sorted, -> { order(:name) }
26
26
  scope :subscribable, -> { all }
27
27
 
28
- # Creates or builds all the Lists
28
+ # Reads all the InterestCategories from Mailchimp and creates local MailchimpCategory records
29
+ # This is part of the Sync changes from Mailchimp button
29
30
  def self.sync!(api: EffectiveMailchimp.api)
30
31
  # For every mailchimp_list, get all the categories
31
32
  mailchimp_lists = Effective::MailchimpList.all
@@ -33,7 +33,8 @@ module Effective
33
33
  scope :sorted, -> { order(:display_order) }
34
34
  scope :subscribable, -> { where(can_subscribe: true) }
35
35
 
36
- # Creates or builds all the Lists
36
+ # Reads all the InterestCategoriesInterests from Mailchimp and creates local MailchimpInterest records
37
+ # This is part of the Sync changes from Mailchimp button
37
38
  def self.sync!(api: EffectiveMailchimp.api)
38
39
  # For every mailchimp_list, get all the interests
39
40
  mailchimp_lists = Effective::MailchimpList.deep.all
@@ -22,8 +22,10 @@ module Effective
22
22
  scope :sorted, -> { order(:name) }
23
23
  scope :subscribable, -> { where(can_subscribe: true) }
24
24
 
25
- # Creates or builds all the Lists
26
- def self.sync!(api: EffectiveMailchimp.api, merge_fields: nil)
25
+ # Reads all the Lists from Mailchimp and creates local MailchimpList records
26
+ # Also writes our merge fields to Mailchimp if they don't exist
27
+ # This is part of the Sync changes from Mailchimp button
28
+ def self.sync!(api: EffectiveMailchimp.api)
27
29
  # All the Lists from Mailchimp
28
30
  lists = api.lists()
29
31
 
@@ -40,6 +42,7 @@ module Effective
40
42
 
41
43
  web_id: list['web_id'],
42
44
  name: list['name'],
45
+ member_count: (list.dig('stats', 'member_count') || 0),
43
46
  updated_at: Time.zone.now
44
47
  )
45
48
 
@@ -54,21 +57,34 @@ module Effective
54
57
  end
55
58
 
56
59
  # Sync merge fields
57
- if merge_fields.present?
60
+ if (merge_fields = EffectiveMailchimp.merge_fields).present?
58
61
  merge_field_keys = merge_fields.keys.map(&:to_s)
59
62
 
60
63
  mailchimp_lists.reject(&:destroyed?).each do |mailchimp_list|
61
64
  existing = api.list_merge_fields(mailchimp_list).map { |hash| hash['tag'] }
62
- (merge_field_keys - existing).each do |name|
63
- puts "Adding merge field #{name} to #{mailchimp_list}"
64
- api.add_merge_field(mailchimp_list, name: name)
65
- end
65
+ (merge_field_keys - existing).each { |name| api.add_merge_field(mailchimp_list, name: name) }
66
66
  end
67
67
  end
68
68
 
69
69
  true
70
70
  end
71
71
 
72
+ def subscribe_all_users!(now: false)
73
+ if now
74
+ subscribe_all!(EffectiveMailchimp.User.all)
75
+ else
76
+ EffectiveMailchimpSubscribeAllUsersJob.perform_later(self)
77
+ end
78
+ end
79
+
80
+ def subscribe_all_members!(now: false)
81
+ if now
82
+ subscribe_all!(EffectiveMailchimp.User.all.members)
83
+ else
84
+ EffectiveMailchimpSubscribeAllMembersJob.perform_later(self)
85
+ end
86
+ end
87
+
72
88
  def to_s
73
89
  name.presence || model_name.human
74
90
  end
@@ -94,5 +110,21 @@ module Effective
94
110
  EffectiveMailchimp.api.admin_url + "/lists/settings/merge-tags?id=#{web_id}"
95
111
  end
96
112
 
113
+ private
114
+
115
+ def subscribe_all!(users)
116
+ users.find_each do |user|
117
+ begin
118
+ user.mailchimp_subscribe!(self, subscribed: true, now: true)
119
+ rescue => e
120
+ EffectiveLogger.error(e.message, associated: user) if defined?(EffectiveLogger)
121
+ ExceptionNotifier.notify_exception(e, data: { user_id: user.id, mailchimp_list_id: id }) if defined?(ExceptionNotifier)
122
+ raise(e) if Rails.env.test? || Rails.env.development?
123
+ end
124
+ end
125
+
126
+ true
127
+ end
128
+
97
129
  end
98
130
  end
@@ -20,14 +20,13 @@
20
20
  = link_to('campaigns', EffectiveMailchimp.api.campaigns_url, target: '_blank')
21
21
  at anytime.
22
22
 
23
- %p.text-muted
24
- %small
25
- To change the names or display order of items below, please visit the Mailchimp website then sync changes.
26
- %br
27
- This operation also creates the audience merge fields and updates the subscriber counts for each group below.
23
+ %p To change the names or display order of items below, please visit the Mailchimp website then sync changes.
28
24
 
29
25
  = render('admin/mailchimp/sync')
30
26
 
27
+ %p.text-muted
28
+ %small This operation also creates the audience merge fields and updates the member and subscriber counts below.
29
+
31
30
  = collapse('More settings') do
32
31
  %p
33
32
  For more information see
@@ -44,7 +43,7 @@
44
43
  %p The following merge fields are sent to Mailchimp when a user subscribes:
45
44
 
46
45
  %ul
47
- - current_user.mailchimp_merge_fields.keys.sort.each do |key|
46
+ - EffectiveMailchimp.merge_fields.keys.sort.each do |key|
48
47
  %li= key
49
48
 
50
49
  .mb-4
@@ -60,7 +59,7 @@
60
59
  Press the Edit button to change the Can Subscribe and Force Subscribe settings.
61
60
 
62
61
  - datatable = Admin::EffectiveMailchimpListsDatatable.new
63
- = render_datatable(datatable, simple: true, inline: true)
62
+ = render_datatable(datatable, inline: true, short: true, search: false, sort: false)
64
63
 
65
64
  = card(Effective::MailchimpCategory) do
66
65
  %p
@@ -76,5 +75,5 @@
76
75
  - Effective::MailchimpCategory.all.each do |mailchimp_category|
77
76
  = card(mailchimp_category.to_s) do
78
77
  - datatable = Admin::EffectiveMailchimpInterestsDatatable.new(mailchimp_category: mailchimp_category)
79
- = render_datatable(datatable, simple: true, inline: true)
78
+ = render_datatable(datatable, inline: true, short: true, search: false, sort: false)
80
79
 
@@ -5,4 +5,10 @@ EffectiveMailchimp.setup do |config|
5
5
 
6
6
  # Mailchimp Settings
7
7
  config.api_key = '' # From mailchimp's /account/api/ screen
8
+
9
+ # In Sandbox Mode you can only READ from Mailchimp not actually write to it
10
+ config.sandbox_mode = false
11
+
12
+ # Assign the User class name. For use in determining all merge_fields
13
+ # config.user_class_name = 'User'
8
14
  end
data/config/routes.rb CHANGED
@@ -13,7 +13,11 @@ EffectiveMailchimp::Engine.routes.draw do
13
13
  end
14
14
 
15
15
  namespace :admin do
16
- resources :mailchimp_lists, only: [:index, :edit, :update]
16
+ resources :mailchimp_lists, only: [:index, :edit, :update] do
17
+ post :subscribe_all_users, on: :member
18
+ post :subscribe_all_members, on: :member
19
+ end
20
+
17
21
  resources :mailchimp_interests, only: [:index, :edit, :update]
18
22
  resources :mailchimp_categories, only: :index
19
23
  resources :mailchimp_list_members, only: :index
@@ -5,6 +5,8 @@ class CreateEffectiveMailchimp < ActiveRecord::Migration[6.0]
5
5
  t.string :web_id
6
6
  t.string :name
7
7
 
8
+ t.integer :member_count
9
+
8
10
  t.boolean :can_subscribe
9
11
  t.boolean :force_subscribe
10
12
 
@@ -1,3 +1,3 @@
1
1
  module EffectiveMailchimp
2
- VERSION = '0.7.0'.freeze
2
+ VERSION = '0.8.0'.freeze
3
3
  end
@@ -9,7 +9,7 @@ module EffectiveMailchimp
9
9
  [
10
10
  :mailchimp_lists_table_name, :mailchimp_list_members_table_name, :mailchimp_categories_table_name, :mailchimp_interests_table_name,
11
11
  :layout,
12
- :api_key
12
+ :api_key, :sandbox_mode, :user_class_name
13
13
  ]
14
14
  end
15
15
 
@@ -19,6 +19,10 @@ module EffectiveMailchimp
19
19
  Effective::MailchimpApi.new(api_key: api_key)
20
20
  end
21
21
 
22
+ def self.sandbox_mode?
23
+ !!sandbox_mode
24
+ end
25
+
22
26
  def self.api_present?
23
27
  api_key.present?
24
28
  end
@@ -27,6 +31,23 @@ module EffectiveMailchimp
27
31
  api_key.blank?
28
32
  end
29
33
 
34
+ def self.User
35
+ klass = user_class_name.constantize if user_class_name.present?
36
+ klass ||= Tenant.User if defined?(Tenant)
37
+ klass ||= '::User'.safe_constantize
38
+
39
+ raise('unable to determine User klass. Please set config.user_class_name') unless klass.kind_of?(Class)
40
+ raise('expecting an effective_mailchimp_user User class') unless klass.respond_to?(:effective_mailchimp_user)
41
+
42
+ klass
43
+ end
44
+
45
+ def self.merge_fields
46
+ merge_fields = self.User().new.mailchimp_merge_fields
47
+ raise('expected a Hash of merge fields') unless merge_fields.kind_of?(Hash)
48
+ merge_fields
49
+ end
50
+
30
51
  def self.permitted_params
31
52
  [ :mailchimp_user_form_action, mailchimp_list_members_attributes: [:id, :mailchimp_list_id, :subscribed, interests: []] ]
32
53
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_mailchimp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code and Effect
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-07-05 00:00:00.000000000 Z
11
+ date: 2024-07-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -204,6 +204,8 @@ files:
204
204
  - app/datatables/admin/effective_mailchimp_list_members_datatable.rb
205
205
  - app/datatables/admin/effective_mailchimp_lists_datatable.rb
206
206
  - app/helpers/effective_mailchimp_helper.rb
207
+ - app/jobs/effective_mailchimp_subscribe_all_members_job.rb
208
+ - app/jobs/effective_mailchimp_subscribe_all_users_job.rb
207
209
  - app/jobs/effective_mailchimp_update_job.rb
208
210
  - app/models/concerns/effective_mailchimp_user.rb
209
211
  - app/models/effective/mailchimp_api.rb