caffeinate 2.4 → 2.6.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 +14 -1
- data/app/models/caffeinate/campaign_subscription.rb +4 -3
- data/app/models/caffeinate/mailing.rb +4 -3
- data/lib/caffeinate/dripper_collection.rb +9 -0
- data/lib/caffeinate/rspec/helpers.rb +5 -0
- data/lib/caffeinate/version.rb +1 -1
- data/lib/caffeinate.rb +4 -0
- data/lib/generators/caffeinate/install_generator.rb +37 -0
- data/lib/generators/caffeinate/templates/migrations/create_caffeinate_campaign_subscriptions.rb.tt +4 -4
- data/lib/generators/caffeinate/templates/migrations/create_caffeinate_campaigns.rb.tt +5 -1
- data/lib/generators/caffeinate/templates/migrations/create_caffeinate_mailings.rb.tt +2 -2
- metadata +75 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 80b37c2c81ad72352314b1515575b4b5d91c78356d8d534075eff1a9bc161881
|
|
4
|
+
data.tar.gz: de05a62c92be2eec505bf3beabda4488f4a8292c12285745c4eb34c880b8ac1a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2bca9ae1ca715af5abdedb012610a6ff397fbe109176798fcc87e8de8e9b1f24e1282d525289baad168be41c11c8401eca740b09430f843cdeacdb07aefff439
|
|
7
|
+
data.tar.gz: 5fb91cdf1517ffe52c1cd474ddb53dbf2b912fd49975307697ff6ed43bc7660da2946feb770e2cb6cb5ce49615dee5bce2bd7b10b68a90dd5781ef53fb20ef75
|
data/README.md
CHANGED
|
@@ -152,6 +152,19 @@ $ rails g caffeinate:install
|
|
|
152
152
|
$ rake db:migrate
|
|
153
153
|
```
|
|
154
154
|
|
|
155
|
+
Optionally, use different flags for supporting `bigint` or `uuid`:
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# UUID with pgcrypto (PostgreSQL < 13)
|
|
159
|
+
rails g caffeinate:install --uuid
|
|
160
|
+
|
|
161
|
+
# UUID without pgcrypto (PostgreSQL 13+)
|
|
162
|
+
rails g caffeinate:install --uuid --skip-pgcrypto
|
|
163
|
+
|
|
164
|
+
# Or via primary-key-type
|
|
165
|
+
rails g caffeinate:install --primary-key-type=uuid --skip-pgcrypto
|
|
166
|
+
```
|
|
167
|
+
|
|
155
168
|
### Clean up the business logic
|
|
156
169
|
|
|
157
170
|
Assuming you intend to use Caffeinate to handle emails using ActionMailer, mailers should be responsible for receiving context and creating a `mail` object. Nothing more. (If you are looking for examples that don't use ActionMailer, see [Without ActionMailer](docs/6-without-action-mailer.md).)
|
|
@@ -255,7 +268,7 @@ Caffeinate also...
|
|
|
255
268
|
* ✅ Tested against large databases at AngelList and is performant as hell
|
|
256
269
|
* ✅ Effortlessly handles complex workflows
|
|
257
270
|
- Need to skip a certain mailing? You can!
|
|
258
|
-
|
|
271
|
+
|
|
259
272
|
## Documentation
|
|
260
273
|
|
|
261
274
|
* [Getting started, tips and tricks](https://github.com/joshmn/caffeinate/blob/master/docs/README.md)
|
|
@@ -27,8 +27,8 @@ module Caffeinate
|
|
|
27
27
|
class CampaignSubscription < ApplicationRecord
|
|
28
28
|
self.table_name = 'caffeinate_campaign_subscriptions'
|
|
29
29
|
|
|
30
|
-
has_many :caffeinate_mailings, class_name: 'Caffeinate::Mailing', foreign_key: :caffeinate_campaign_subscription_id, dependent: :destroy
|
|
31
|
-
has_many :mailings, class_name: 'Caffeinate::Mailing', foreign_key: :caffeinate_campaign_subscription_id, dependent: :destroy
|
|
30
|
+
has_many :caffeinate_mailings, -> { order(send_at: :asc) }, class_name: 'Caffeinate::Mailing', foreign_key: :caffeinate_campaign_subscription_id, dependent: :destroy
|
|
31
|
+
has_many :mailings, -> { order(send_at: :asc) }, class_name: 'Caffeinate::Mailing', foreign_key: :caffeinate_campaign_subscription_id, dependent: :destroy
|
|
32
32
|
has_many :future_mailings, -> { upcoming.unsent }, class_name: '::Caffeinate::Mailing', foreign_key: :caffeinate_campaign_subscription_id
|
|
33
33
|
|
|
34
34
|
has_one :next_caffeinate_mailing, -> { joins(:caffeinate_campaign_subscription).where(caffeinate_campaign_subscriptions: { ended_at: nil, unsubscribed_at: nil }).upcoming.unsent.order(send_at: :asc) }, class_name: '::Caffeinate::Mailing', foreign_key: :caffeinate_campaign_subscription_id
|
|
@@ -38,7 +38,8 @@ module Caffeinate
|
|
|
38
38
|
has_one :previous_mailing, -> { sent.order(sent_at: :desc) }, class_name: '::Caffeinate::Mailing', foreign_key: :caffeinate_campaign_subscription_id
|
|
39
39
|
|
|
40
40
|
belongs_to :caffeinate_campaign, class_name: 'Caffeinate::Campaign', foreign_key: :caffeinate_campaign_id
|
|
41
|
-
|
|
41
|
+
alias_method :campaign, :caffeinate_campaign
|
|
42
|
+
alias_method :campaign=, :caffeinate_campaign=
|
|
42
43
|
|
|
43
44
|
belongs_to :subscriber, polymorphic: true
|
|
44
45
|
belongs_to :user, polymorphic: true, optional: true
|
|
@@ -20,9 +20,10 @@ module Caffeinate
|
|
|
20
20
|
self.table_name = 'caffeinate_mailings'
|
|
21
21
|
|
|
22
22
|
belongs_to :caffeinate_campaign_subscription, class_name: 'Caffeinate::CampaignSubscription'
|
|
23
|
-
|
|
23
|
+
alias_method :subscription, :caffeinate_campaign_subscription
|
|
24
|
+
alias_method :subscription=, :caffeinate_campaign_subscription=
|
|
24
25
|
has_one :caffeinate_campaign, through: :caffeinate_campaign_subscription
|
|
25
|
-
|
|
26
|
+
alias_method :campaign, :caffeinate_campaign
|
|
26
27
|
|
|
27
28
|
scope :upcoming, -> { joins(:caffeinate_campaign_subscription).where(caffeinate_campaign_subscription: ::Caffeinate::CampaignSubscription.active).unsent.unskipped.where('send_at < ?', ::Caffeinate.config.time_now).order('send_at asc') }
|
|
28
29
|
scope :unsent, -> { unskipped.where(sent_at: nil) }
|
|
@@ -131,7 +132,7 @@ module Caffeinate
|
|
|
131
132
|
end
|
|
132
133
|
|
|
133
134
|
def end_if_no_mailings!
|
|
134
|
-
end! if future_mailings.empty?
|
|
135
|
+
caffeinate_campaign_subscription.end! if caffeinate_campaign_subscription.future_mailings.empty?
|
|
135
136
|
end
|
|
136
137
|
end
|
|
137
138
|
end
|
|
@@ -20,6 +20,15 @@ module Caffeinate
|
|
|
20
20
|
@registry.values
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
+
# Caffeinate maintains a couple of class-variables under the hood
|
|
24
|
+
# that don't get reset between specs (while the db records they cache do
|
|
25
|
+
# get truncated). This resets the appropriate class-variables between specs
|
|
26
|
+
def clear_cache!
|
|
27
|
+
drippers.each do |dripper|
|
|
28
|
+
dripper.safe_constantize&.instance_variable_set(:@caffeinate_campaign, nil)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
23
32
|
def clear!
|
|
24
33
|
@registry = {}
|
|
25
34
|
end
|
data/lib/caffeinate/version.rb
CHANGED
data/lib/caffeinate.rb
CHANGED
|
@@ -8,6 +8,43 @@ module Caffeinate
|
|
|
8
8
|
|
|
9
9
|
desc 'Creates a Caffeinate initializer and copies migrations to your application.'
|
|
10
10
|
|
|
11
|
+
class_option :uuid, type: :boolean, default: false,
|
|
12
|
+
desc: 'Use UUID primary keys'
|
|
13
|
+
|
|
14
|
+
class_option :primary_key_type, type: :string, default: nil,
|
|
15
|
+
desc: 'Primary key type: uuid, bigint, or integer (default)'
|
|
16
|
+
|
|
17
|
+
class_option :skip_pgcrypto, type: :boolean, default: false,
|
|
18
|
+
desc: 'Skip pgcrypto extension (PostgreSQL 13+ has gen_random_uuid built-in)'
|
|
19
|
+
|
|
20
|
+
def primary_key_type
|
|
21
|
+
return :uuid if options[:uuid]
|
|
22
|
+
return options[:primary_key_type].to_sym if options[:primary_key_type]
|
|
23
|
+
nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def primary_key_option
|
|
27
|
+
return '' unless primary_key_type
|
|
28
|
+
", id: :#{primary_key_type}"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def foreign_key_type
|
|
32
|
+
return '' unless primary_key_type
|
|
33
|
+
", type: :#{primary_key_type}"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def column_type_for_polymorphic
|
|
37
|
+
case primary_key_type
|
|
38
|
+
when :uuid then :uuid
|
|
39
|
+
when :bigint then :bigint
|
|
40
|
+
else :integer
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def enable_pgcrypto?
|
|
45
|
+
primary_key_type == :uuid && !options[:skip_pgcrypto]
|
|
46
|
+
end
|
|
47
|
+
|
|
11
48
|
# :nodoc:
|
|
12
49
|
def copy_initializer
|
|
13
50
|
template 'caffeinate.rb', 'config/initializers/caffeinate.rb'
|
data/lib/generators/caffeinate/templates/migrations/create_caffeinate_campaign_subscriptions.rb.tt
CHANGED
|
@@ -4,12 +4,12 @@ class CreateCaffeinateCampaignSubscriptions < ActiveRecord::Migration<%= migrati
|
|
|
4
4
|
def change
|
|
5
5
|
drop_table :caffeinate_campaign_subscriptions if table_exists?(:caffeinate_campaign_subscriptions)
|
|
6
6
|
|
|
7
|
-
create_table :caffeinate_campaign_subscriptions do |t|
|
|
8
|
-
t.references :caffeinate_campaign, null: false, index: { name: :caffeineate_campaign_subscriptions_on_campaign }, foreign_key: true
|
|
7
|
+
create_table :caffeinate_campaign_subscriptions<%= primary_key_option %> do |t|
|
|
8
|
+
t.references :caffeinate_campaign, null: false, index: { name: :caffeineate_campaign_subscriptions_on_campaign }, foreign_key: true<%= foreign_key_type %>
|
|
9
9
|
t.string :subscriber_type, null: false
|
|
10
|
-
t
|
|
10
|
+
t.<%= column_type_for_polymorphic %> :subscriber_id, null: false
|
|
11
11
|
t.string :user_type
|
|
12
|
-
t
|
|
12
|
+
t.<%= column_type_for_polymorphic %> :user_id
|
|
13
13
|
t.string :token, null: false
|
|
14
14
|
t.datetime :ended_at
|
|
15
15
|
t.string :ended_reason
|
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
class CreateCaffeinateCampaigns < ActiveRecord::Migration<%= migration_version %>
|
|
4
4
|
def change
|
|
5
|
-
|
|
5
|
+
<% if enable_pgcrypto? -%>
|
|
6
|
+
enable_extension 'pgcrypto' unless extension_enabled?('pgcrypto')
|
|
7
|
+
|
|
8
|
+
<% end -%>
|
|
9
|
+
create_table :caffeinate_campaigns<%= primary_key_option %> do |t|
|
|
6
10
|
t.string :name, null: false
|
|
7
11
|
t.string :slug, null: false
|
|
8
12
|
t.boolean :active, default: true, null: false
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
class CreateCaffeinateMailings < ActiveRecord::Migration<%= migration_version %>
|
|
4
4
|
def change
|
|
5
|
-
create_table :caffeinate_mailings do |t|
|
|
6
|
-
t.references :caffeinate_campaign_subscription, null: false, foreign_key: true, index: { name: 'index_caffeinate_mailings_on_campaign_subscription' }
|
|
5
|
+
create_table :caffeinate_mailings<%= primary_key_option %> do |t|
|
|
6
|
+
t.references :caffeinate_campaign_subscription, null: false, foreign_key: true, index: { name: 'index_caffeinate_mailings_on_campaign_subscription' }<%= foreign_key_type %>
|
|
7
7
|
t.datetime :send_at, null: false
|
|
8
8
|
t.datetime :sent_at
|
|
9
9
|
t.datetime :skipped_at
|
metadata
CHANGED
|
@@ -1,17 +1,58 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: caffeinate
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 2.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Josh Brody
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
|
-
name:
|
|
13
|
+
name: activerecord
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: 5.0.0
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: 5.0.0
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: actionpack
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: 5.0.0
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: 5.0.0
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: actionmailer
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: 5.0.0
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: 5.0.0
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: actionview
|
|
15
56
|
requirement: !ruby/object:Gem::Requirement
|
|
16
57
|
requirements:
|
|
17
58
|
- - ">="
|
|
@@ -94,6 +135,20 @@ dependencies:
|
|
|
94
135
|
- - ">="
|
|
95
136
|
- !ruby/object:Gem::Version
|
|
96
137
|
version: '0'
|
|
138
|
+
- !ruby/object:Gem::Dependency
|
|
139
|
+
name: pg
|
|
140
|
+
requirement: !ruby/object:Gem::Requirement
|
|
141
|
+
requirements:
|
|
142
|
+
- - ">="
|
|
143
|
+
- !ruby/object:Gem::Version
|
|
144
|
+
version: '0'
|
|
145
|
+
type: :development
|
|
146
|
+
prerelease: false
|
|
147
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
148
|
+
requirements:
|
|
149
|
+
- - ">="
|
|
150
|
+
- !ruby/object:Gem::Version
|
|
151
|
+
version: '0'
|
|
97
152
|
- !ruby/object:Gem::Dependency
|
|
98
153
|
name: sqlite3
|
|
99
154
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -108,6 +163,20 @@ dependencies:
|
|
|
108
163
|
- - ">="
|
|
109
164
|
- !ruby/object:Gem::Version
|
|
110
165
|
version: '0'
|
|
166
|
+
- !ruby/object:Gem::Dependency
|
|
167
|
+
name: sprockets-rails
|
|
168
|
+
requirement: !ruby/object:Gem::Requirement
|
|
169
|
+
requirements:
|
|
170
|
+
- - ">="
|
|
171
|
+
- !ruby/object:Gem::Version
|
|
172
|
+
version: '0'
|
|
173
|
+
type: :development
|
|
174
|
+
prerelease: false
|
|
175
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
176
|
+
requirements:
|
|
177
|
+
- - ">="
|
|
178
|
+
- !ruby/object:Gem::Version
|
|
179
|
+
version: '0'
|
|
111
180
|
- !ruby/object:Gem::Dependency
|
|
112
181
|
name: timecop
|
|
113
182
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -191,6 +260,7 @@ files:
|
|
|
191
260
|
- lib/caffeinate/perform.rb
|
|
192
261
|
- lib/caffeinate/periodical_drip.rb
|
|
193
262
|
- lib/caffeinate/rspec.rb
|
|
263
|
+
- lib/caffeinate/rspec/helpers.rb
|
|
194
264
|
- lib/caffeinate/rspec/matchers.rb
|
|
195
265
|
- lib/caffeinate/rspec/matchers/be_subscribed_to_caffeinate_campaign.rb
|
|
196
266
|
- lib/caffeinate/rspec/matchers/end_caffeinate_campaign_subscription.rb
|
|
@@ -212,7 +282,6 @@ homepage: https://github.com/joshmn/caffeinate
|
|
|
212
282
|
licenses:
|
|
213
283
|
- MIT
|
|
214
284
|
metadata: {}
|
|
215
|
-
post_install_message:
|
|
216
285
|
rdoc_options: []
|
|
217
286
|
require_paths:
|
|
218
287
|
- lib
|
|
@@ -227,8 +296,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
227
296
|
- !ruby/object:Gem::Version
|
|
228
297
|
version: '0'
|
|
229
298
|
requirements: []
|
|
230
|
-
rubygems_version:
|
|
231
|
-
signing_key:
|
|
299
|
+
rubygems_version: 4.0.1
|
|
232
300
|
specification_version: 4
|
|
233
301
|
summary: Create, manage, and send scheduled email sequences and drip campaigns from
|
|
234
302
|
your Rails app.
|