caffeinate 0.1.0 → 0.2.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 +4 -4
- data/README.md +2 -2
- data/app/controllers/caffeinate/campaign_subscriptions_controller.rb +17 -2
- data/app/models/caffeinate/campaign.rb +11 -1
- data/app/models/caffeinate/campaign_subscription.rb +22 -5
- data/app/models/caffeinate/mailing.rb +18 -2
- data/app/views/caffeinate/campaign_subscriptions/subscribe.html.erb +3 -0
- data/app/views/caffeinate/campaign_subscriptions/unsubscribe.html.erb +3 -0
- data/app/views/layouts/caffeinate.html.erb +11 -0
- data/config/locales/en.yml +6 -0
- data/lib/caffeinate.rb +1 -0
- data/lib/caffeinate/action_mailer/extension.rb +11 -1
- data/lib/caffeinate/action_mailer/interceptor.rb +1 -1
- data/lib/caffeinate/action_mailer/observer.rb +3 -3
- data/lib/caffeinate/active_record/extension.rb +1 -1
- data/lib/caffeinate/drip.rb +10 -35
- data/lib/caffeinate/drip_evaluator.rb +33 -0
- data/lib/caffeinate/dripper/base.rb +2 -10
- data/lib/caffeinate/dripper/campaign.rb +1 -1
- data/lib/caffeinate/dripper/defaults.rb +1 -1
- data/lib/caffeinate/dripper/delivery.rb +1 -1
- data/lib/caffeinate/dripper/drip.rb +19 -5
- data/lib/caffeinate/dripper/inferences.rb +26 -0
- data/lib/caffeinate/dripper/perform.rb +4 -2
- data/lib/caffeinate/dripper/subscriber.rb +2 -2
- data/lib/caffeinate/engine.rb +11 -0
- data/lib/caffeinate/helpers.rb +21 -0
- data/lib/caffeinate/url_helpers.rb +7 -0
- data/lib/caffeinate/version.rb +1 -1
- data/lib/generators/caffeinate/templates/{application_campaign.rb → application_dripper.rb} +0 -0
- metadata +15 -15
- data/app/views/layouts/caffeinate/application.html.erb +0 -15
- data/app/views/layouts/caffeinate/campaign_subscriptions/unsubscribe.html.erb +0 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3032e43fad1742429e8961a3bfca1e522c9fcf19714c8cc998d6dea629c30a6e
|
|
4
|
+
data.tar.gz: a51f59c2d0767d18002051827590d31a7ab0b96ae570a1c048d0a37ab4446007
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ede225ce8d0fbb71214411d38366ea43992da7b95428734af5c4134f496c04d2dbf2b4a940f19ffbbf24dde9c4536834b96051bd493ec3476897f6f376b2324a
|
|
7
|
+
data.tar.gz: acc6124e88a4d8e6beced5afc80e7774de78b60858940e579f821ed172ad14f6a033e7b0419c105c233806f94005f98d4dab73f25bbb53e40175d7dca289c9f2
|
data/README.md
CHANGED
|
@@ -2,18 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
module Caffeinate
|
|
4
4
|
class CampaignSubscriptionsController < ApplicationController
|
|
5
|
+
layout 'caffeinate'
|
|
6
|
+
|
|
7
|
+
helper_method :caffeinate_unsubscribe_url, :caffeinate_subscribe_url
|
|
8
|
+
|
|
5
9
|
before_action :find_campaign_subscription!
|
|
6
10
|
|
|
7
11
|
def unsubscribe
|
|
8
12
|
@campaign_subscription.unsubscribe!
|
|
9
|
-
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def subscribe
|
|
16
|
+
@campaign_subscription.subscribe!
|
|
10
17
|
end
|
|
11
18
|
|
|
12
19
|
private
|
|
13
20
|
|
|
21
|
+
def caffeinate_subscribe_url(**options)
|
|
22
|
+
Caffeinate::UrlHelpers.caffeinate_subscribe_url(@campaign_subscription, options)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def caffeinate_unsubscribe_url
|
|
26
|
+
Caffeinate::UrlHelpers.caffeinate_unsubscribe_url(@campaign_subscription, options)
|
|
27
|
+
end
|
|
28
|
+
|
|
14
29
|
def find_campaign_subscription!
|
|
15
30
|
@campaign_subscription = ::Caffeinate::CampaignSubscription.find_by(token: params[:token])
|
|
16
|
-
|
|
31
|
+
raise ::ActiveRecord::RecordNotFound if @campaign_subscription.nil?
|
|
17
32
|
end
|
|
18
33
|
end
|
|
19
34
|
end
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
# == Schema Information
|
|
4
|
+
#
|
|
5
|
+
# Table name: caffeinate_campaigns
|
|
6
|
+
#
|
|
7
|
+
# id :integer not null, primary key
|
|
8
|
+
# name :string not null
|
|
9
|
+
# slug :string not null
|
|
10
|
+
# created_at :datetime not null
|
|
11
|
+
# updated_at :datetime not null
|
|
12
|
+
#
|
|
3
13
|
module Caffeinate
|
|
4
|
-
# Campaign.
|
|
14
|
+
# Campaign ties together subscribers and mailings, and provides one core model for handling your Drippers.
|
|
5
15
|
class Campaign < ApplicationRecord
|
|
6
16
|
self.table_name = 'caffeinate_campaigns'
|
|
7
17
|
has_many :caffeinate_campaign_subscriptions, class_name: 'Caffeinate::CampaignSubscription', foreign_key: :caffeinate_campaign_id
|
|
@@ -1,12 +1,29 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
# == Schema Information
|
|
4
|
+
#
|
|
5
|
+
# Table name: caffeinate_campaign_subscriptions
|
|
6
|
+
#
|
|
7
|
+
# id :integer not null, primary key
|
|
8
|
+
# caffeinate_campaign_id :integer not null
|
|
9
|
+
# subscriber_type :string not null
|
|
10
|
+
# subscriber_id :string not null
|
|
11
|
+
# user_type :string
|
|
12
|
+
# user_id :string
|
|
13
|
+
# token :string not null
|
|
14
|
+
# ended_at :datetime
|
|
15
|
+
# unsubscribed_at :datetime
|
|
16
|
+
# created_at :datetime not null
|
|
17
|
+
# updated_at :datetime not null
|
|
18
|
+
#
|
|
3
19
|
module Caffeinate
|
|
4
|
-
# CampaignSubscription associates an object and its optional user to a Campaign
|
|
20
|
+
# CampaignSubscription associates an object and its optional user to a Campaign
|
|
21
|
+
# and its relevant Mailings.
|
|
5
22
|
class CampaignSubscription < ApplicationRecord
|
|
6
23
|
self.table_name = 'caffeinate_campaign_subscriptions'
|
|
7
24
|
|
|
8
25
|
has_many :caffeinate_mailings, class_name: 'Caffeinate::Mailing', foreign_key: :caffeinate_campaign_subscription_id
|
|
9
|
-
has_one :next_caffeinate_mailing, -> { upcoming.unsent.limit(1).first }, class_name: 'Caffeinate::Mailing', foreign_key: :caffeinate_campaign_subscription_id
|
|
26
|
+
has_one :next_caffeinate_mailing, -> { upcoming.unsent.limit(1).first }, class_name: '::Caffeinate::Mailing', foreign_key: :caffeinate_campaign_subscription_id
|
|
10
27
|
belongs_to :caffeinate_campaign, class_name: 'Caffeinate::Campaign', foreign_key: :caffeinate_campaign_id
|
|
11
28
|
belongs_to :subscriber, polymorphic: true
|
|
12
29
|
belongs_to :user, polymorphic: true, optional: true
|
|
@@ -37,12 +54,12 @@ module Caffeinate
|
|
|
37
54
|
!ended? && !unsubscribed?
|
|
38
55
|
end
|
|
39
56
|
|
|
40
|
-
# Checks if the CampaignSubscription is not subscribed
|
|
57
|
+
# Checks if the CampaignSubscription is not subscribed by checking the presence of `unsubscribed_at`
|
|
41
58
|
def unsubscribed?
|
|
42
|
-
|
|
59
|
+
unsubscribed_at.present?
|
|
43
60
|
end
|
|
44
61
|
|
|
45
|
-
# Checks if the CampaignSubscription is ended
|
|
62
|
+
# Checks if the CampaignSubscription is ended by checking the presence of `ended_at`
|
|
46
63
|
def ended?
|
|
47
64
|
ended_at.present?
|
|
48
65
|
end
|
|
@@ -1,8 +1,24 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
# == Schema Information
|
|
4
|
+
#
|
|
5
|
+
# Table name: caffeinate_mailings
|
|
6
|
+
#
|
|
7
|
+
# id :integer not null, primary key
|
|
8
|
+
# caffeinate_campaign_subscription_id :integer not null
|
|
9
|
+
# send_at :datetime
|
|
10
|
+
# sent_at :datetime
|
|
11
|
+
# skipped_at :datetime
|
|
12
|
+
# mailer_class :string not null
|
|
13
|
+
# mailer_action :string not null
|
|
14
|
+
# created_at :datetime not null
|
|
15
|
+
# updated_at :datetime not null
|
|
16
|
+
#
|
|
3
17
|
module Caffeinate
|
|
4
18
|
# Records of the mails sent and to be sent for a given `::Caffeinate::CampaignSubscriber`
|
|
5
19
|
class Mailing < ApplicationRecord
|
|
20
|
+
CURRENT_THREAD_KEY = :current_caffeinate_mailing.freeze
|
|
21
|
+
|
|
6
22
|
self.table_name = 'caffeinate_mailings'
|
|
7
23
|
|
|
8
24
|
belongs_to :caffeinate_campaign_subscription, class_name: 'Caffeinate::CampaignSubscription'
|
|
@@ -49,7 +65,7 @@ module Caffeinate
|
|
|
49
65
|
# The associated drip
|
|
50
66
|
# @todo This can be optimized with a better cache
|
|
51
67
|
def drip
|
|
52
|
-
@drip ||= caffeinate_campaign.to_dripper.
|
|
68
|
+
@drip ||= caffeinate_campaign.to_dripper.drip_collection[mailer_action]
|
|
53
69
|
end
|
|
54
70
|
|
|
55
71
|
# The associated Subscriber from `::Caffeinate::CampaignSubscription`
|
|
@@ -64,7 +80,7 @@ module Caffeinate
|
|
|
64
80
|
|
|
65
81
|
# Assigns attributes to the Mailing from the Drip
|
|
66
82
|
def from_drip(drip)
|
|
67
|
-
self.send_at = drip.
|
|
83
|
+
self.send_at = drip.send_at
|
|
68
84
|
self.mailer_class = drip.options[:mailer_class]
|
|
69
85
|
self.mailer_action = drip.action
|
|
70
86
|
self
|
data/lib/caffeinate.rb
CHANGED
|
@@ -5,8 +5,18 @@ module Caffeinate
|
|
|
5
5
|
module Extension
|
|
6
6
|
def self.included(klass)
|
|
7
7
|
klass.before_action do
|
|
8
|
-
@mailing = Thread.current[
|
|
8
|
+
@mailing = Thread.current[::Caffeinate::Mailing::CURRENT_THREAD_KEY] if Thread.current[::Caffeinate::Mailing::CURRENT_THREAD_KEY]
|
|
9
9
|
end
|
|
10
|
+
|
|
11
|
+
klass.helper_method :caffeinate_unsubscribe_url, :caffeinate_subscribe_url
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def caffeinate_unsubscribe_url(**options)
|
|
15
|
+
Caffeinate::UrlHelpers.caffeinate_unsubscribe_url(@mailing.caffeinate_campaign_subscription, **options)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def caffeinate_subscribe_url
|
|
19
|
+
Caffeinate::UrlHelpers.caffeinate_subscribe_url(@mailing.caffeinate_campaign_subscription, **options)
|
|
10
20
|
end
|
|
11
21
|
end
|
|
12
22
|
end
|
|
@@ -5,7 +5,7 @@ module Caffeinate
|
|
|
5
5
|
class Interceptor
|
|
6
6
|
# Handles `before_send` callbacks for a `Caffeinate::Dripper`
|
|
7
7
|
def self.delivering_email(message)
|
|
8
|
-
mailing = Thread.current[
|
|
8
|
+
mailing = Thread.current[::Caffeinate::Mailing::CURRENT_THREAD_KEY]
|
|
9
9
|
return unless mailing
|
|
10
10
|
|
|
11
11
|
mailing.caffeinate_campaign.to_dripper.run_callbacks(:before_send, mailing.caffeinate_campaign_subscription, mailing, message)
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
module Caffeinate
|
|
4
4
|
module ActionMailer
|
|
5
|
-
# Handles updating the Caffeinate::Message if it's available in Thread.current[
|
|
5
|
+
# Handles updating the Caffeinate::Message if it's available in Thread.current[::Caffeinate::Mailing::CURRENT_THREAD_KEY]
|
|
6
6
|
# and runs any associated callbacks
|
|
7
7
|
class Observer
|
|
8
8
|
def self.delivered_email(message)
|
|
9
|
-
mailing = Thread.current[
|
|
9
|
+
mailing = Thread.current[::Caffeinate::Mailing::CURRENT_THREAD_KEY]
|
|
10
10
|
return unless mailing
|
|
11
11
|
|
|
12
|
-
mailing.update!(sent_at: Caffeinate.config.time_now) if message.perform_deliveries
|
|
12
|
+
mailing.update!(sent_at: Caffeinate.config.time_now, skipped_at: nil) if message.perform_deliveries
|
|
13
13
|
mailing.caffeinate_campaign.to_dripper.run_callbacks(:after_send, mailing.caffeinate_campaign_subscription, mailing, message)
|
|
14
14
|
end
|
|
15
15
|
end
|
|
@@ -9,7 +9,7 @@ module Caffeinate
|
|
|
9
9
|
has_many :caffeinate_campaigns, through: :caffeinate_campaign_subscriptions, class_name: '::Caffeinate::Campaign'
|
|
10
10
|
has_many :caffeinate_mailings, through: :caffeinate_campaign_subscriptions, class_name: '::Caffeinate::Mailing'
|
|
11
11
|
|
|
12
|
-
scope :
|
|
12
|
+
scope :not_subscribed_to_campaign, lambda { |list|
|
|
13
13
|
subscribed = ::Caffeinate::CampaignSubscription.select(:subscriber_id).joins(:caffeinate_campaign).where(caffeinate_campaigns: { slug: list }, subscriber_type: name)
|
|
14
14
|
where.not(id: subscribed)
|
|
15
15
|
}
|
data/lib/caffeinate/drip.rb
CHANGED
|
@@ -1,40 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'caffeinate/drip_evaluator'
|
|
3
4
|
module Caffeinate
|
|
4
5
|
# A Drip object
|
|
6
|
+
#
|
|
7
|
+
# Handles the block and provides convenience methods for the drip
|
|
5
8
|
class Drip
|
|
6
|
-
# Handles the block and provides convenience methods for the drip
|
|
7
|
-
class Evaluator
|
|
8
|
-
attr_reader :mailing
|
|
9
|
-
def initialize(mailing)
|
|
10
|
-
@mailing = mailing
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def call(&block)
|
|
14
|
-
return true unless block
|
|
15
|
-
|
|
16
|
-
instance_eval(&block)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
# Ends the CampaignSubscription
|
|
20
|
-
def end!
|
|
21
|
-
mailing.caffeinate_campaign_subscription.end!
|
|
22
|
-
false
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# Unsubscribes the CampaignSubscription
|
|
26
|
-
def unsubscribe!
|
|
27
|
-
mailing.caffeinate_campaign_subscription.unsubscribe!
|
|
28
|
-
false
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
# Skips the mailing
|
|
32
|
-
def skip!
|
|
33
|
-
mailing.skip!
|
|
34
|
-
false
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
9
|
attr_reader :dripper, :action, :options, :block
|
|
39
10
|
def initialize(dripper, action, options, &block)
|
|
40
11
|
@dripper = dripper
|
|
@@ -43,14 +14,18 @@ module Caffeinate
|
|
|
43
14
|
@block = block
|
|
44
15
|
end
|
|
45
16
|
|
|
46
|
-
# If the associated ActionMailer uses `ActionMailer::Parameterized` initialization
|
|
17
|
+
# If the associated ActionMailer uses `ActionMailer::Parameterized` initialization instead of argument-based initialization
|
|
47
18
|
def parameterized?
|
|
48
19
|
options[:using] == :parameterized
|
|
49
20
|
end
|
|
50
21
|
|
|
51
|
-
|
|
22
|
+
def send_at
|
|
23
|
+
options[:delay].from_now
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Checks if the drip is enabled
|
|
52
27
|
def enabled?(mailing)
|
|
53
|
-
|
|
28
|
+
DripEvaluator.new(mailing).call(&@block)
|
|
54
29
|
end
|
|
55
30
|
end
|
|
56
31
|
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module Caffeinate
|
|
2
|
+
# Handles evaluating the `drip` block and provides convenience methods for handling the mailing or its campaign.
|
|
3
|
+
class DripEvaluator
|
|
4
|
+
attr_reader :mailing
|
|
5
|
+
def initialize(mailing)
|
|
6
|
+
@mailing = mailing
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def call(&block)
|
|
10
|
+
return true unless block
|
|
11
|
+
|
|
12
|
+
instance_eval(&block)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Ends the CampaignSubscription
|
|
16
|
+
def end!
|
|
17
|
+
mailing.caffeinate_campaign_subscription.end!
|
|
18
|
+
false
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Unsubscribes the CampaignSubscription
|
|
22
|
+
def unsubscribe!
|
|
23
|
+
mailing.caffeinate_campaign_subscription.unsubscribe!
|
|
24
|
+
false
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Skips the mailing
|
|
28
|
+
def skip!
|
|
29
|
+
mailing.skip!
|
|
30
|
+
false
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'caffeinate/dripper/drip'
|
|
4
|
+
require 'caffeinate/dripper/inferences'
|
|
4
5
|
require 'caffeinate/dripper/callbacks'
|
|
5
6
|
require 'caffeinate/dripper/defaults'
|
|
6
7
|
require 'caffeinate/dripper/subscriber'
|
|
@@ -16,18 +17,9 @@ module Caffeinate
|
|
|
16
17
|
include Defaults
|
|
17
18
|
include Delivery
|
|
18
19
|
include Drip
|
|
20
|
+
include Inferences
|
|
19
21
|
include Perform
|
|
20
22
|
include Subscriber
|
|
21
|
-
|
|
22
|
-
# The inferred mailer class
|
|
23
|
-
def self.inferred_mailer_class
|
|
24
|
-
klass_name = "#{name.delete_suffix('Dripper')}Mailer"
|
|
25
|
-
klass = klass_name.safe_constantize
|
|
26
|
-
return nil unless klass
|
|
27
|
-
return klass_name if klass < ::ActionMailer::Base
|
|
28
|
-
|
|
29
|
-
nil
|
|
30
|
-
end
|
|
31
23
|
end
|
|
32
24
|
end
|
|
33
25
|
end
|
|
@@ -23,7 +23,7 @@ module Caffeinate
|
|
|
23
23
|
# @param [Hash] options The options to set defaults with
|
|
24
24
|
# @option options [String] :mailer_class The mailer class
|
|
25
25
|
def default(options = {})
|
|
26
|
-
options.assert_valid_keys(:mailer_class, :mailer)
|
|
26
|
+
options.assert_valid_keys(:mailer_class, :mailer, :using)
|
|
27
27
|
@defaults = options
|
|
28
28
|
end
|
|
29
29
|
end
|
|
@@ -14,7 +14,7 @@ module Caffeinate
|
|
|
14
14
|
#
|
|
15
15
|
# @param [Caffeinate::Mailing] mailing The mailing to deliver
|
|
16
16
|
def deliver!(mailing)
|
|
17
|
-
Thread.current[
|
|
17
|
+
Thread.current[::Caffeinate::Mailing::CURRENT_THREAD_KEY] = mailing
|
|
18
18
|
|
|
19
19
|
if mailing.drip.parameterized?
|
|
20
20
|
mailing.mailer_class.constantize.with(mailing: mailing).send(mailing.mailer_action).deliver
|
|
@@ -10,21 +10,29 @@ module Caffeinate
|
|
|
10
10
|
|
|
11
11
|
def initialize(dripper)
|
|
12
12
|
@dripper = dripper
|
|
13
|
-
@drips =
|
|
13
|
+
@drips = {}
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
# Register the drip
|
|
17
17
|
def register(action, options, &block)
|
|
18
|
-
@drips
|
|
18
|
+
@drips[action.to_s] = ::Caffeinate::Drip.new(@dripper, action, options, &block)
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def each(&block)
|
|
22
|
-
@drips.each { |drip| block.call(drip) }
|
|
22
|
+
@drips.each { |action_name, drip| block.call(action_name, drip) }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def values
|
|
26
|
+
@drips.values
|
|
23
27
|
end
|
|
24
28
|
|
|
25
29
|
def size
|
|
26
30
|
@drips.size
|
|
27
31
|
end
|
|
32
|
+
|
|
33
|
+
def [](val)
|
|
34
|
+
@drips[val]
|
|
35
|
+
end
|
|
28
36
|
end
|
|
29
37
|
|
|
30
38
|
# :nodoc:
|
|
@@ -33,9 +41,14 @@ module Caffeinate
|
|
|
33
41
|
end
|
|
34
42
|
|
|
35
43
|
module ClassMethods
|
|
44
|
+
# A collection of Drip objects associated with a given `Caffeinate::Dripper`
|
|
45
|
+
def drip_collection
|
|
46
|
+
@drip_collection ||= DripCollection.new(self)
|
|
47
|
+
end
|
|
48
|
+
|
|
36
49
|
# A collection of Drip objects associated with a given `Caffeinate::Dripper`
|
|
37
50
|
def drips
|
|
38
|
-
|
|
51
|
+
drip_collection.values
|
|
39
52
|
end
|
|
40
53
|
|
|
41
54
|
# Register a drip on the Dripper
|
|
@@ -50,6 +63,7 @@ module Caffeinate
|
|
|
50
63
|
def drip(action_name, options = {}, &block)
|
|
51
64
|
options.assert_valid_keys(:mailer_class, :step, :delay, :using, :mailer)
|
|
52
65
|
options[:mailer_class] ||= options[:mailer] || defaults[:mailer_class]
|
|
66
|
+
options[:using] ||= defaults[:using]
|
|
53
67
|
options[:step] ||= drips.size + 1
|
|
54
68
|
|
|
55
69
|
if options[:mailer_class].nil?
|
|
@@ -57,7 +71,7 @@ module Caffeinate
|
|
|
57
71
|
end
|
|
58
72
|
raise ArgumentError, "You must define :delay in the options for :#{action_name}" if options[:delay].nil?
|
|
59
73
|
|
|
60
|
-
|
|
74
|
+
drip_collection.register(action_name, options, &block)
|
|
61
75
|
end
|
|
62
76
|
end
|
|
63
77
|
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Caffeinate
|
|
2
|
+
module Dripper
|
|
3
|
+
module Inferences
|
|
4
|
+
def self.included(klass)
|
|
5
|
+
klass.extend ClassMethods
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
module ClassMethods
|
|
9
|
+
# The inferred mailer class
|
|
10
|
+
def inferred_mailer_class
|
|
11
|
+
klass_name = "#{name.delete_suffix('Dripper')}Mailer"
|
|
12
|
+
klass = klass_name.safe_constantize
|
|
13
|
+
return nil unless klass
|
|
14
|
+
return klass_name if klass < ::ActionMailer::Base
|
|
15
|
+
|
|
16
|
+
nil
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# The inferred mailer class
|
|
20
|
+
def inferred_campaign_slug
|
|
21
|
+
"#{name.delete_suffix('Dripper')}".underscore
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -15,8 +15,10 @@ module Caffeinate
|
|
|
15
15
|
#
|
|
16
16
|
# @return nil
|
|
17
17
|
def perform!
|
|
18
|
-
campaign.caffeinate_campaign_subscriptions.
|
|
19
|
-
subscriber.next_caffeinate_mailing
|
|
18
|
+
campaign.caffeinate_campaign_subscriptions.active.includes(:next_caffeinate_mailing).each do |subscriber|
|
|
19
|
+
if subscriber.next_caffeinate_mailing
|
|
20
|
+
subscriber.next_caffeinate_mailing.process!
|
|
21
|
+
end
|
|
20
22
|
end
|
|
21
23
|
true
|
|
22
24
|
end
|
|
@@ -30,8 +30,8 @@ module Caffeinate
|
|
|
30
30
|
# @option [ActiveRecord::Base] :user The associated user (optional)
|
|
31
31
|
#
|
|
32
32
|
# @return [Caffeinate::CampaignSubscriber] the created CampaignSubscriber
|
|
33
|
-
def subscribe(subscriber,
|
|
34
|
-
caffeinate_campaign.subscribe(subscriber,
|
|
33
|
+
def subscribe(subscriber, **args)
|
|
34
|
+
caffeinate_campaign.subscribe(subscriber, **args)
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
# :nodoc:
|
data/lib/caffeinate/engine.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'caffeinate/helpers'
|
|
3
4
|
require 'caffeinate/action_mailer'
|
|
4
5
|
require 'caffeinate/active_record/extension'
|
|
5
6
|
|
|
@@ -8,6 +9,12 @@ module Caffeinate
|
|
|
8
9
|
class Engine < ::Rails::Engine
|
|
9
10
|
isolate_namespace Caffeinate
|
|
10
11
|
|
|
12
|
+
config.to_prepare do
|
|
13
|
+
Dir.glob(Rails.root.join("app/drippers/**/*.rb")).each do |file|
|
|
14
|
+
require file
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
11
18
|
ActiveSupport.on_load(:action_mailer) do
|
|
12
19
|
include ::Caffeinate::ActionMailer::Extension
|
|
13
20
|
::ActionMailer::Base.register_interceptor(::Caffeinate::ActionMailer::Interceptor)
|
|
@@ -17,5 +24,9 @@ module Caffeinate
|
|
|
17
24
|
ActiveSupport.on_load(:active_record) do
|
|
18
25
|
extend ::Caffeinate::ActiveRecord::Extension
|
|
19
26
|
end
|
|
27
|
+
|
|
28
|
+
ActiveSupport.on_load(:action_view) do
|
|
29
|
+
ApplicationHelper.send(:include, ::Caffeinate::Helpers)
|
|
30
|
+
end
|
|
20
31
|
end
|
|
21
32
|
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Caffeinate
|
|
2
|
+
module Helpers
|
|
3
|
+
def caffeinate_unsubscribe_url(subscription, **options)
|
|
4
|
+
opts = (::ActionMailer::Base.default_url_options || {}).merge(options)
|
|
5
|
+
Caffeinate::Engine.routes.url_helpers.unsubscribe_campaign_subscription_url(token: subscription.token, **opts)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def caffeinate_subscribe_url(subscription, **options)
|
|
9
|
+
opts = (::ActionMailer::Base.default_url_options || {}).merge(options)
|
|
10
|
+
Caffeinate::Engine.routes.url_helpers.subscribe_campaign_subscription_url(token: subscription.token, **opts)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def caffeinate_unsubscribe_path(subscription, **options)
|
|
14
|
+
Caffeinate::Engine.routes.url_helpers.unsubscribe_campaign_subscription_path(token: subscription.token, **options)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def caffeinate_subscribe_path(subscription, **options)
|
|
18
|
+
Caffeinate::Engine.routes.url_helpers.subscribe_campaign_subscription_path(token: subscription.token, **options)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
data/lib/caffeinate/version.rb
CHANGED
|
File without changes
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: caffeinate
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Josh Brody
|
|
@@ -14,22 +14,16 @@ dependencies:
|
|
|
14
14
|
name: rails
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- - "~>"
|
|
18
|
-
- !ruby/object:Gem::Version
|
|
19
|
-
version: 6.0.3
|
|
20
17
|
- - ">="
|
|
21
18
|
- !ruby/object:Gem::Version
|
|
22
|
-
version:
|
|
19
|
+
version: 5.0.0
|
|
23
20
|
type: :runtime
|
|
24
21
|
prerelease: false
|
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
26
23
|
requirements:
|
|
27
|
-
- - "~>"
|
|
28
|
-
- !ruby/object:Gem::Version
|
|
29
|
-
version: 6.0.3
|
|
30
24
|
- - ">="
|
|
31
25
|
- !ruby/object:Gem::Version
|
|
32
|
-
version:
|
|
26
|
+
version: 5.0.0
|
|
33
27
|
- !ruby/object:Gem::Dependency
|
|
34
28
|
name: factory_bot_rails
|
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -114,7 +108,7 @@ dependencies:
|
|
|
114
108
|
- - ">="
|
|
115
109
|
- !ruby/object:Gem::Version
|
|
116
110
|
version: '0'
|
|
117
|
-
description:
|
|
111
|
+
description: Ruby on Rails drip campaign engine. Buzzwords!
|
|
118
112
|
email:
|
|
119
113
|
- josh@josh.mn
|
|
120
114
|
executables: []
|
|
@@ -130,8 +124,10 @@ files:
|
|
|
130
124
|
- app/models/caffeinate/campaign.rb
|
|
131
125
|
- app/models/caffeinate/campaign_subscription.rb
|
|
132
126
|
- app/models/caffeinate/mailing.rb
|
|
133
|
-
- app/views/
|
|
134
|
-
- app/views/
|
|
127
|
+
- app/views/caffeinate/campaign_subscriptions/subscribe.html.erb
|
|
128
|
+
- app/views/caffeinate/campaign_subscriptions/unsubscribe.html.erb
|
|
129
|
+
- app/views/layouts/caffeinate.html.erb
|
|
130
|
+
- config/locales/en.yml
|
|
135
131
|
- config/routes.rb
|
|
136
132
|
- db/migrate/20201124183102_create_caffeinate_campaigns.rb
|
|
137
133
|
- db/migrate/20201124183303_create_caffeinate_campaign_subscriptions.rb
|
|
@@ -146,18 +142,22 @@ files:
|
|
|
146
142
|
- lib/caffeinate/configuration.rb
|
|
147
143
|
- lib/caffeinate/deliver_async.rb
|
|
148
144
|
- lib/caffeinate/drip.rb
|
|
145
|
+
- lib/caffeinate/drip_evaluator.rb
|
|
149
146
|
- lib/caffeinate/dripper/base.rb
|
|
150
147
|
- lib/caffeinate/dripper/callbacks.rb
|
|
151
148
|
- lib/caffeinate/dripper/campaign.rb
|
|
152
149
|
- lib/caffeinate/dripper/defaults.rb
|
|
153
150
|
- lib/caffeinate/dripper/delivery.rb
|
|
154
151
|
- lib/caffeinate/dripper/drip.rb
|
|
152
|
+
- lib/caffeinate/dripper/inferences.rb
|
|
155
153
|
- lib/caffeinate/dripper/perform.rb
|
|
156
154
|
- lib/caffeinate/dripper/subscriber.rb
|
|
157
155
|
- lib/caffeinate/engine.rb
|
|
156
|
+
- lib/caffeinate/helpers.rb
|
|
157
|
+
- lib/caffeinate/url_helpers.rb
|
|
158
158
|
- lib/caffeinate/version.rb
|
|
159
159
|
- lib/generators/caffeinate/install_generator.rb
|
|
160
|
-
- lib/generators/caffeinate/templates/
|
|
160
|
+
- lib/generators/caffeinate/templates/application_dripper.rb
|
|
161
161
|
- lib/generators/caffeinate/templates/caffeinate.rb
|
|
162
162
|
homepage: https://github.com/joshmn/caffeinate
|
|
163
163
|
licenses:
|
|
@@ -178,8 +178,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
178
178
|
- !ruby/object:Gem::Version
|
|
179
179
|
version: '0'
|
|
180
180
|
requirements: []
|
|
181
|
-
rubygems_version: 3.0.
|
|
181
|
+
rubygems_version: 3.2.0.rc.2
|
|
182
182
|
signing_key:
|
|
183
183
|
specification_version: 4
|
|
184
|
-
summary:
|
|
184
|
+
summary: Ruby on Rails drip campaign engine. Buzzwords!
|
|
185
185
|
test_files: []
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<h5>You have been unsubscribed.</h5>
|