effective_mailchimp 0.2.5 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1bfe4116a697ecf8159efedc227cef01e8ba67e6a66af101df8f13939145ab3b
4
- data.tar.gz: 6ec420f5b33544b57d355cb924eb116312df32a7f43cf21f5846d328e09bddf1
3
+ metadata.gz: 6a5caed2328b202f012d4c813afb0c5038aa304b6b7efdcf30097bcc7ff7be2e
4
+ data.tar.gz: ed2fb79473591925eaf5ac5f2556464afb01269370e173215988afa33630dd12
5
5
  SHA512:
6
- metadata.gz: c1510628c55b5bb1d50848b6a0ab1d5c3e486b00dd809ba97a7c85e33cee9803bdf3a07c75e3190b8744b4d2245c304918dc267a40c42da955ffb0097b74296a
7
- data.tar.gz: 47e46744ee8e61be5662b976053c820df9832af56546a4b822a811044cc2843badc1209c1f0bc4fe3e993d895a43b815078b42fe218a44f40564996a955297a5
6
+ metadata.gz: 272d0eda1823ee5df64c6f32612707cf5a80cabcd27b8cfd1ed346b2dc6e95142482e81fbc4f8c2bbd8afbce92be580898685b4c6833c83728bd30a408f8f9d4
7
+ data.tar.gz: 33c4543526fe5b465f4a2252482fd5d9774f62a06f2b82cc825274599f0e3f53f0a5f48891e66c4cb983451669f23e4e201c7979f4207e30e0051c7f49696f69
@@ -3,11 +3,18 @@ module Admin
3
3
  before_action(:authenticate_user!) if defined?(Devise)
4
4
  before_action { EffectiveResources.authorize!(self, :admin, :effective_mailchimp) }
5
5
 
6
- # Calls Sync
7
- before_action(only: :index) { Effective::MailchimpList.sync! }
8
-
9
6
  include Effective::CrudController
10
7
 
8
+ def mailchimp_sync
9
+ EffectiveResources.authorize!(self, :mailchimp_sync, Effective::MailchimpList)
10
+
11
+ Effective::MailchimpList.sync!
12
+
13
+ flash[:success] = "Successfully synced mailchimp lists"
14
+
15
+ redirect_back(fallback_location: effective_mailchimp.admin_mailchimp_lists_path)
16
+ end
17
+
11
18
  private
12
19
 
13
20
  def permitted_params
@@ -0,0 +1,18 @@
1
+ module Effective
2
+ class MailchimpController < ApplicationController
3
+ before_action(:authenticate_user!) if defined?(Devise)
4
+
5
+ def mailchimp_sync_user
6
+ resource = current_user
7
+
8
+ EffectiveResources.authorize!(self, :mailchimp_sync_user, current_user)
9
+
10
+ resource.mailchimp_sync!
11
+
12
+ flash[:success] = "Successfully synced mailchimp"
13
+
14
+ redirect_back(fallback_location: '/settings')
15
+ end
16
+
17
+ end
18
+ end
@@ -1,15 +1,2 @@
1
1
  module EffectiveMailchimpHelper
2
-
3
- def mailchimp_user_fields(form)
4
- raise('expected a form') unless form.respond_to?(:object)
5
-
6
- resource = form.object
7
- raise('expected an effective_mailchimp_user resource') unless resource.class.respond_to?(:effective_mailchimp_user?)
8
-
9
- resource.reload
10
- resource.mailchimp_sync!(force: false)
11
-
12
- render('effective/mailchimp_user/fields', form: form, f: form, resource: resource, mailchimp_user: resource)
13
- end
14
-
15
2
  end
@@ -2,7 +2,7 @@ class EffectiveMailchimpUpdateJob < ApplicationJob
2
2
 
3
3
  def perform(user)
4
4
  raise('expected an effective_mailchimp_user') unless user.class.try(:effective_mailchimp_user?)
5
- user.mailchimp_update!(force: true)
5
+ user.mailchimp_update!
6
6
  end
7
7
 
8
8
  end
@@ -14,6 +14,10 @@ module EffectiveMailchimpUser
14
14
 
15
15
  module ClassMethods
16
16
  def effective_mailchimp_user?; true; end
17
+
18
+ def require_mailchimp_update_fields
19
+ ['email', 'last_name', 'first_name']
20
+ end
17
21
  end
18
22
 
19
23
  included do
@@ -26,11 +30,54 @@ module EffectiveMailchimpUser
26
30
  accepts_nested_attributes_for :mailchimp_lists, allow_destroy: true
27
31
 
28
32
  # The user updated the form
29
- after_commit(if: -> { mailchimp_user_form_action }) do
33
+ after_commit(if: -> { mailchimp_member_update_required? }) do
30
34
  EffectiveMailchimpUpdateJob.perform_later(self)
31
35
  end
32
36
  end
33
37
 
38
+ def mailchimp_subscribed?(mailchimp_list)
39
+ raise('expected a MailchimpList') unless mailchimp_lists.all? { |list| list.kind_of?(Effective::MailchimpList) }
40
+
41
+ member = mailchimp_list_member(mailchimp_list: mailchimp_list)
42
+ return false if member.blank?
43
+
44
+ member.subscribed? && member.synced?
45
+ end
46
+
47
+ # Api method to just subscribe this user to this list right now
48
+ # Pass one list or an Array of lists
49
+ def mailchimp_subscribe!(mailchimp_list)
50
+ mailchimp_lists = Array(mailchimp_list)
51
+ raise('expected a MailchimpList') unless mailchimp_lists.all? { |list| list.kind_of?(Effective::MailchimpList) }
52
+
53
+ mailchimp_lists.each do |mailchimp_list|
54
+ member = build_mailchimp_list_member(mailchimp_list: mailchimp_list)
55
+ member.assign_attributes(subscribed: true)
56
+ end
57
+
58
+ # This sets up the after_commit to run the mailchimp_update! job
59
+ assign_attributes(mailchimp_user_form_action: true)
60
+
61
+ save!
62
+ end
63
+
64
+ # Api method to just unsubscribe this user to this list right now
65
+ # Pass one list or an Array of lists
66
+ def mailchimp_unsubscribe!(mailchimp_list)
67
+ mailchimp_lists = Array(mailchimp_list)
68
+ raise('expected a MailchimpList') unless mailchimp_lists.all? { |list| list.kind_of?(Effective::MailchimpList) }
69
+
70
+ mailchimp_lists.each do |mailchimp_list|
71
+ member = build_mailchimp_list_member(mailchimp_list: mailchimp_list)
72
+ member.assign_attributes(subscribed: false)
73
+ end
74
+
75
+ # This sets up the after_commit to run the mailchimp_update! job
76
+ assign_attributes(mailchimp_user_form_action: true)
77
+
78
+ save!
79
+ end
80
+
34
81
  # Intended for app to extend
35
82
  def mailchimp_merge_fields
36
83
  default_mailchimp_merge_fields()
@@ -88,26 +135,29 @@ module EffectiveMailchimpUser
88
135
  mailchimp_list_member(mailchimp_list: mailchimp_list) || mailchimp_list_members.build(mailchimp_list: mailchimp_list)
89
136
  end
90
137
 
91
- def mailchimp_list_members_changed?
92
- mailchimp_list_members.any? { |mlm| mlm.changes.present? || mlm.marked_for_destruction? }
93
- end
94
-
95
138
  def mailchimp_last_synced_at
96
- mailchimp_list_members.map(&:last_synced_at).min
139
+ mailchimp_list_members.map(&:last_synced_at).compact.min
97
140
  end
98
141
 
99
- def mailchimp_sync_required?
100
- return true if mailchimp_last_synced_at.blank?
101
- mailchimp_last_synced_at < (Time.zone.now - 1.day)
142
+ # Used by the form to set it up for all lists
143
+ def build_mailchimp_list_members
144
+ mailchimp_lists = Effective::MailchimpList.subscribable.sorted.to_a
145
+
146
+ mailchimp_lists.each do |mailchimp_list|
147
+ build_mailchimp_list_member(mailchimp_list: mailchimp_list)
148
+ end
149
+
150
+ mailchimp_list_members
102
151
  end
103
152
 
104
153
  # Pulls the current status from Mailchimp API into the Mailchimp List Member objects
105
154
  # Run before the mailchimp fields are displayed
106
- def mailchimp_sync!(force: true)
155
+ # Only run in the background when a user or admin clicks sync now
156
+ def mailchimp_sync!
107
157
  api = EffectiveMailchimp.api
108
158
  lists = Effective::MailchimpList.subscribable.sorted.to_a
109
159
 
110
- return if lists.length == mailchimp_list_members.length && !(force || mailchimp_sync_required?)
160
+ assign_attributes(mailchimp_user_form_action: nil)
111
161
 
112
162
  Timeout::timeout(lists.length * 2) do
113
163
  lists.each do |mailchimp_list|
@@ -123,12 +173,12 @@ module EffectiveMailchimpUser
123
173
  member.mark_for_destruction unless list.present?
124
174
  end
125
175
 
126
- save! if mailchimp_list_members_changed?
127
- true
176
+ save!
128
177
  end
129
178
 
130
179
  # Pushes the current Mailchimp List Member objects to Mailchimp when needed
131
- def mailchimp_update!(force: true)
180
+ # Called in the background after a form submission that changes the user email/last_name/first_name or mailchimp subscriptions
181
+ def mailchimp_update!
132
182
  api = EffectiveMailchimp.api
133
183
 
134
184
  assign_attributes(mailchimp_user_form_action: nil)
@@ -137,24 +187,28 @@ module EffectiveMailchimpUser
137
187
  if member.mailchimp_id.blank? && member.subscribed?
138
188
  list_member = api.list_member_add(member)
139
189
  member.assign_mailchimp_attributes(list_member)
140
- elsif member.mailchimp_id.present? && (force || mailchimp_member_update_required?(member))
190
+ elsif member.mailchimp_id.present?
141
191
  list_member = api.list_member_update(member)
142
192
  member.assign_mailchimp_attributes(list_member)
143
193
  end
144
194
  end
145
195
 
146
- save! if mailchimp_list_members_changed?
147
- true
196
+ save!
148
197
  end
149
198
 
150
- def mailchimp_member_update_required?(member)
151
- require_update = ['email', 'last_name', 'first_name']
199
+ private
200
+
201
+ def mailchimp_member_update_required?
202
+ return false unless mailchimp_user_form_action
152
203
 
204
+ # Update if my email first name or last name change
205
+ require_update = self.class.require_mailchimp_update_fields()
153
206
  return true if (changes.keys & require_update).present?
154
207
  return true if (previous_changes.keys & require_update).present?
155
208
 
156
- return true if member.changes.present?
157
- return true if member.previous_changes.present?
209
+ # Update if any of my mailchimp list members changed
210
+ # which happens when I submit a form and change the Mailchimp values
211
+ return true if mailchimp_list_members.any? { |m| m.changes.present? || m.previous_changes.present? || m.marked_for_destruction? }
158
212
 
159
213
  false
160
214
  end
@@ -21,10 +21,18 @@ module Effective
21
21
  @client.set_config(api_key: @api_key, server: @server)
22
22
  end
23
23
 
24
+ def debug?
25
+ Rails.env.development?
26
+ end
27
+
24
28
  def admin_url
25
29
  "https://#{server}.admin.mailchimp.com"
26
30
  end
27
31
 
32
+ def public_url
33
+ "https://mailchimp.com"
34
+ end
35
+
28
36
  def ping
29
37
  client.ping.get()
30
38
  end
@@ -32,11 +40,15 @@ module Effective
32
40
  # Returns an Array of Lists, which are each Hash
33
41
  # Like this [{ ...}, { ... }]
34
42
  def lists
43
+ Rails.logger.info "[effective_mailchimp] Index Lists..." if debug?
44
+
35
45
  response = client.lists.get_all_lists(count: 250)
36
46
  Array(response['lists']) - [nil, '', {}]
37
47
  end
38
48
 
39
49
  def list(id)
50
+ Rails.logger.info "[effective_mailchimp] Show List..." if debug?
51
+
40
52
  client.lists.get_list(id.try(:mailchimp_id) || id)
41
53
  end
42
54
 
@@ -70,6 +82,9 @@ module Effective
70
82
  def list_member_add(member)
71
83
  raise('expected an Effective::MailchimpListMember') unless member.kind_of?(Effective::MailchimpListMember)
72
84
 
85
+ existing = list_member(member.mailchimp_list, member.user.email)
86
+ return existing if existing.present?
87
+
73
88
  merge_fields = member.user.mailchimp_merge_fields
74
89
  raise('expected user mailchimp_merge_fields to be a Hash') unless merge_fields.kind_of?(Hash)
75
90
 
@@ -21,6 +21,8 @@ module Effective
21
21
  timestamps
22
22
  end
23
23
 
24
+ validates :mailchimp_list_id, uniqueness: { scope: [:user_type, :user_id] }
25
+
24
26
  scope :deep, -> { includes(:mailchimp_list, :user) }
25
27
  scope :sorted, -> { order(:id) }
26
28
 
@@ -43,5 +45,9 @@ module Effective
43
45
  )
44
46
  end
45
47
 
48
+ def synced?
49
+ last_synced_at.present?
50
+ end
51
+
46
52
  end
47
53
  end
@@ -1,16 +1,20 @@
1
1
  %h1.effective-admin-heading= @page_title
2
2
 
3
- .card
4
- .card-body
5
- = collapse('Show merge field settings') do
6
- %p The following Merge fields are sent to Mailchimp when a user subscribes:
3
+ - resource = (@_effective_resource || Effective::Resource.new(controller_path))
7
4
 
8
- %ul
9
- - current_user.mailchimp_merge_fields.keys.each do |key|
10
- %li= key
5
+ .resource-buttons
6
+ = render_resource_buttons(resource.klass, (action ||= :index) => false)
11
7
 
12
- %p To have these fields displayed in Mailchimp, please configure each campaign with any of these merge fields.
8
+ = card do
9
+ = collapse('Show merge field settings') do
10
+ %p The following Merge fields are sent to Mailchimp when a user subscribes:
13
11
 
14
- .mb-4
12
+ %ul
13
+ - current_user.mailchimp_merge_fields.keys.each do |key|
14
+ %li= key
15
15
 
16
- = render_datatable @datatable
16
+ %p To have these fields displayed in Mailchimp, please configure each campaign with any of these merge fields.
17
+
18
+ .mb-4
19
+
20
+ = render_datatable @datatable
@@ -12,18 +12,7 @@
12
12
  = effective_form_with model: [:admin, user] do |f|
13
13
  = f.hidden_field :id
14
14
 
15
- = mailchimp_user_fields(f)
16
-
17
- %p.text-muted
18
- %small
19
- last synced with
20
- = link_to 'Mailchimp', EffectiveMailchimp.api.admin_url
21
- - if user.mailchimp_last_synced_at.present?
22
- = time_ago_in_words(user.mailchimp_last_synced_at)
23
- ago.
24
- - else
25
- never.
26
-
27
- = link_to 'sync now', effective_mailchimp.mailchimp_sync_user_admin_mailchimp_path(f.object), 'data-method': :post
15
+ = render('effective/mailchimp_user/fields', f: f)
16
+ = render('admin/mailchimp_user/sync', f: f)
28
17
 
29
18
  = f.submit
@@ -0,0 +1,15 @@
1
+ - user = f.object
2
+
3
+ - if user.persisted?
4
+ %p.text-muted
5
+ %small
6
+ last synced with
7
+ = link_to 'Mailchimp', EffectiveMailchimp.api.admin_url, target: '_blank'
8
+ - if user.mailchimp_last_synced_at.present?
9
+ = time_ago_in_words(user.mailchimp_last_synced_at)
10
+ ago.
11
+ - else
12
+ never.
13
+
14
+ - if EffectiveResources.authorized?(self, :mailchimp_sync_user, user)
15
+ = link_to 'sync now', effective_mailchimp.mailchimp_sync_user_admin_mailchimp_path(user), 'data-method': :post
@@ -1,12 +1,15 @@
1
1
  = f.hidden_field :mailchimp_user_form_action, value: true
2
2
 
3
- = f.fields_for :mailchimp_list_members do |fmlm|
3
+ = f.fields_for :mailchimp_list_members, f.object.build_mailchimp_list_members do |fmlm|
4
4
  - mailchimp_list = fmlm.object.mailchimp_list
5
5
  - next if mailchimp_list.blank?
6
6
 
7
+ = fmlm.hidden_field :id
8
+ = fmlm.hidden_field :mailchimp_list_id
9
+
7
10
  - if mailchimp_list.force_subscribe?
8
11
  %p
9
- = fmlm.check_box :subscribed, label: fmlm.object.to_s, disabled: true, hint: 'required'
12
+ = fmlm.check_box :subscribed, label: fmlm.object.to_s, disabled: true, hint: 'required', checked: true
10
13
  = fmlm.hidden_field :subscribed, value: true
11
14
 
12
15
  - elsif mailchimp_list.can_subscribe?
@@ -0,0 +1,15 @@
1
+ - user = f.object
2
+
3
+ - if user.persisted?
4
+ %p.text-muted
5
+ %small
6
+ last synced with
7
+ = link_to 'Mailchimp', EffectiveMailchimp.api.public_url, target: '_blank'
8
+ - if user.mailchimp_last_synced_at.present?
9
+ = time_ago_in_words(user.mailchimp_last_synced_at)
10
+ ago.
11
+ - else
12
+ never.
13
+
14
+ - if EffectiveResources.authorized?(self, :mailchimp_sync_user, user)
15
+ = link_to 'sync now', effective_mailchimp.mailchimp_sync_user_mailchimp_path(user), 'data-method': :post
data/config/routes.rb CHANGED
@@ -7,6 +7,9 @@ end
7
7
  EffectiveMailchimp::Engine.routes.draw do
8
8
  # Public routes
9
9
  scope module: 'effective' do
10
+ resources :mailchimp, only: [] do
11
+ post :mailchimp_sync_user, on: :member
12
+ end
10
13
  end
11
14
 
12
15
  namespace :admin do
@@ -16,12 +19,13 @@ EffectiveMailchimp::Engine.routes.draw do
16
19
 
17
20
  post :force_subscribe, on: :member
18
21
  post :unforce_subscribe, on: :member
22
+
23
+ get :mailchimp_sync, on: :collection
19
24
  end
20
25
 
21
26
  resources :mailchimp, only: [] do
22
27
  post :mailchimp_sync_user, on: :member
23
28
  end
24
-
25
29
  end
26
30
 
27
31
  end
@@ -1,3 +1,3 @@
1
1
  module EffectiveMailchimp
2
- VERSION = '0.2.5'.freeze
2
+ VERSION = '0.3.0'.freeze
3
3
  end
@@ -24,7 +24,7 @@ module EffectiveMailchimp
24
24
  end
25
25
 
26
26
  def self.permitted_params
27
- [ :mailchimp_user_form_action, mailchimp_list_members_attributes: [:id, :subscribed] ]
27
+ [ :mailchimp_user_form_action, mailchimp_list_members_attributes: [:id, :mailchimp_list_id, :subscribed] ]
28
28
  end
29
29
 
30
30
  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.2.5
4
+ version: 0.3.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: 2023-03-24 00:00:00.000000000 Z
11
+ date: 2023-08-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -195,6 +195,7 @@ files:
195
195
  - app/assets/stylesheets/effective_mailchimp/base.scss
196
196
  - app/controllers/admin/mailchimp_controller.rb
197
197
  - app/controllers/admin/mailchimp_lists_controller.rb
198
+ - app/controllers/effective/mailchimp_controller.rb
198
199
  - app/datatables/admin/effective_mailchimp_lists_datatable.rb
199
200
  - app/helpers/effective_mailchimp_helper.rb
200
201
  - app/jobs/effective_mailchimp_update_job.rb
@@ -205,7 +206,9 @@ files:
205
206
  - app/views/admin/mailchimp_lists/_form.html.haml
206
207
  - app/views/admin/mailchimp_lists/index.html.haml
207
208
  - app/views/admin/mailchimp_user/_form.html.haml
209
+ - app/views/admin/mailchimp_user/_sync.html.haml
208
210
  - app/views/effective/mailchimp_user/_fields.html.haml
211
+ - app/views/effective/mailchimp_user/_sync.html.haml
209
212
  - config/effective_mailchimp.rb
210
213
  - config/routes.rb
211
214
  - db/migrate/01_create_effective_mailchimp.rb.erb
@@ -235,7 +238,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
235
238
  - !ruby/object:Gem::Version
236
239
  version: '0'
237
240
  requirements: []
238
- rubygems_version: 3.1.2
241
+ rubygems_version: 3.4.10
239
242
  signing_key:
240
243
  specification_version: 4
241
244
  summary: Subscribe and unsubscribe to mailchimp lists.