heya 0.2.1 → 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: 91788b17940c18fd1196e0cc20f2892fb91233c714a5dc7c876833459ae867d3
4
- data.tar.gz: 6f8694d2562802ff9102fd62e04349beaf464dee5043fd928e0403fd4deb6bab
3
+ metadata.gz: 96972db7d19d5bc0a38361957c0f69e612783c00546441bb82c45c144ac9ff55
4
+ data.tar.gz: 4a52a5d0a83dfe781d68cf7dac1fa06eb74f2074e2d61b2dd651b263b13812df
5
5
  SHA512:
6
- metadata.gz: 7315798099a708fa8bc0477e229672377634a29a97097139c2055ef09edd748edaf4a40a8685cfa015b87e766463ade73c3e10ea71ee41893184bea0ab7867ec
7
- data.tar.gz: 3a437c995a6aaed616b75cce220c80bf28baf7d64364ac1956d11ce1e38c8bbf40d9a71bed97258e84d19d410970ae7ed48d07a6aaed92b92ebc3610ef9b654f
6
+ metadata.gz: cb98d146663bba6e56ce8208a591e1119e1cc033bcba8c902b42504a6947d43118e86dcdffbbf3a7972787df1ed04867db2266dad130802a8eaecd5047e93755
7
+ data.tar.gz: 6af0b7233154b3c17864e568b1b7c6db38336e09e9738d9301d033db46da6db8fe9b6d62e0975dcd06d967e937ce28943c826aa7f851946bb7ab7b647df236ac
@@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.3.0] - 2020-06-02
10
+ ### Added
11
+ - Support I18n translations for email subjects (#81)
12
+
9
13
  ## [0.2.1] - 2020-04-23
10
14
  ### Fixed
11
15
  - Update the install and campaign generators.
data/README.md CHANGED
@@ -3,6 +3,8 @@
3
3
  [![Gem Version](https://badge.fury.io/rb/heya.svg)](https://badge.fury.io/rb/heya)
4
4
  [![Maintainability](https://api.codeclimate.com/v1/badges/a6416e63ffc426715857/maintainability)](https://codeclimate.com/github/honeybadger-io/heya/maintainability)
5
5
 
6
+ [![Twitter Follow](https://img.shields.io/twitter/follow/heyjoshwood?label=Follow%20Josh%20for%20dev%20updates&style=social)](https://mobile.twitter.com/heyjoshwood)
7
+
6
8
  Heya is a campaign mailer for Rails. Think of it like ActionMailer, but for timed email sequences. It can also perform other actions like sending a text message.
7
9
 
8
10
  ## Getting started
@@ -235,19 +237,19 @@ In the above example, Heya will send a message named `:welcome` one day after a
235
237
 
236
238
  The `wait` option tells Heya how long to wait before sending each message (the default is two days). There are a few scheduling options that you can customize for each step:
237
239
 
238
- | Option Name | Default | Description |
239
- |:--|:--|:--|
240
- | `wait` | `2.days` | The duration of time to wait before sending each message |
241
- | `segment` | `nil` | The segment who should receive the message |
242
- | `action` | `Heya::Campaigns::Actions::Email` | The action to perform (usually sending an email) |
243
- | `queue` | `"heya"` | The ActiveJob queue |
240
+ | Option Name | Default | Description |
241
+ | :---------- | :-------------------------------- | :------------------------------------------------------- |
242
+ | `wait` | `2.days` | The duration of time to wait before sending each message |
243
+ | `segment` | `nil` | The segment who should receive the message |
244
+ | `action` | `Heya::Campaigns::Actions::Email` | The action to perform (usually sending an email) |
245
+ | `queue` | `"heya"` | The ActiveJob queue |
244
246
 
245
247
  Heya uses the following additional options to build the message itself:
246
248
 
247
- | Option Name | Default | Description |
248
- |:--|:--|:--|
249
- | `subject` | **required** | The email's subject |
250
- | `from` | Heya default | The sender's email address |
249
+ | Option Name | Default | Description |
250
+ | :---------- | :----------- | :------------------------- |
251
+ | `subject` | **required** | The email's subject |
252
+ | `from` | Heya default | The sender's email address |
251
253
 
252
254
  You can change the default options using the `default` method at the top of the campaign. Heya applies default options to each step which doesn't supply its own:
253
255
 
@@ -264,6 +266,58 @@ class OnboardingCampaign < ApplicationCampaign
264
266
  end
265
267
  ```
266
268
 
269
+ #### Customizing email subjects for each user
270
+
271
+ The subject can be customized for each user by using a `lambda` instead of a `String`:
272
+
273
+ ```ruby
274
+ # app/campaigns/onboarding_campaign.rb
275
+ class OnboardingCampaign < ApplicationCampaign
276
+ step :welcome,
277
+ subject: ->(user) { "Heya #{user.first_name}!" }
278
+ end
279
+ ```
280
+
281
+ #### Translations for email subjects (I18n)
282
+
283
+ If you don't pass a `subject` to the `step` method, Heya will try to find it in your translations. The performed lookup will use the pattern `<campaign_scope>.<step_name>.subject` to construct the key.
284
+
285
+ ```ruby
286
+ # app/campaigns/onboarding_campaign.rb
287
+ class OnboardingCampaign < ApplicationCampaign
288
+ step :welcome
289
+ end
290
+ ```
291
+
292
+ ```yaml
293
+ # config/locales/en.yml
294
+ en:
295
+ onboarding_campaign:
296
+ welcome:
297
+ subject: "Heya!"
298
+ ```
299
+
300
+ To define parameters for interpolation, define a `#heya_attributes` method on your user model:
301
+
302
+ ```ruby
303
+ # app/models/user.rb
304
+ class User < ApplicationRecord
305
+ def heya_attributes
306
+ {
307
+ first_name: name.split(" ").first
308
+ }
309
+ end
310
+ end
311
+ ```
312
+
313
+ ```yaml
314
+ # config/locales/en.yml
315
+ en:
316
+ onboarding_campaign:
317
+ welcome:
318
+ subject: "Heya %{first_name}!"
319
+ ```
320
+
267
321
  ### Custom Actions
268
322
 
269
323
  You can override the default step behavior to perform custom actions by passing
@@ -5,10 +5,17 @@ module Heya
5
5
  def build
6
6
  user = params.fetch(:user)
7
7
  step = params.fetch(:step)
8
- campaign = step.campaign
8
+
9
+ campaign_name = step.campaign_name.underscore
10
+ step_name = step.name.underscore
11
+
9
12
  from = step.params.fetch("from")
10
13
  reply_to = step.params.fetch("reply_to", nil)
11
- subject = step.params.fetch("subject")
14
+
15
+ subject = step.params.fetch("subject") {
16
+ I18n.t("#{campaign_name}.#{step_name}.subject", **attributes_for(user))
17
+ }
18
+ subject = subject.call(user) if subject.respond_to?(:call)
12
19
 
13
20
  instance_variable_set(:"@#{user.model_name.element}", user)
14
21
 
@@ -17,13 +24,21 @@ module Heya
17
24
  reply_to: reply_to,
18
25
  to: user.email,
19
26
  subject: subject,
20
- template_path: "heya/campaign_mailer/#{campaign.name.underscore}",
21
- template_name: step.name.underscore
27
+ template_path: "heya/campaign_mailer/#{campaign_name}",
28
+ template_name: step_name
22
29
  )
23
30
  end
24
31
 
25
32
  protected
26
33
 
34
+ def attributes_for(user)
35
+ if user.respond_to?(:heya_attributes)
36
+ user.heya_attributes.symbolize_keys
37
+ else
38
+ {}
39
+ end
40
+ end
41
+
27
42
  def _prefixes
28
43
  @_prefixes_with_campaign_path ||= begin
29
44
  if params.is_a?(Hash) && (campaign_name = params[:step]&.campaign&.name&.underscore)
@@ -4,6 +4,15 @@ module Heya
4
4
  module Campaigns
5
5
  module Actions
6
6
  class Email < Action
7
+ VALID_PARAMS = %w[subject from reply_to]
8
+
9
+ def self.validate_step(step)
10
+ step.params.assert_valid_keys(VALID_PARAMS)
11
+ unless step.params["subject"].present? || I18n.exists?("#{step.campaign_name.underscore}.#{step.name.underscore}.subject")
12
+ raise ArgumentError.new(%("subject" is required))
13
+ end
14
+ end
15
+
7
16
  def build
8
17
  CampaignMailer
9
18
  .with(user: user, step: step)
@@ -140,13 +140,13 @@ module Heya
140
140
  .merge(opts)
141
141
 
142
142
  attrs = opts.select { |k, _| STEP_ATTRS.key?(k) }
143
- attrs[:params] = opts.reject { |k, _| STEP_ATTRS.key?(k) }.stringify_keys
144
143
  attrs[:id] = "#{self.name}/#{name}"
145
144
  attrs[:name] = name.to_s
146
- attrs[:position] = steps.size
147
145
  attrs[:campaign] = instance
146
+ attrs[:position] = steps.size
147
+ attrs[:params] = opts.reject { |k, _| STEP_ATTRS.key?(k) }.stringify_keys
148
148
 
149
- step = Step.new(attrs)
149
+ step = Step.new(**attrs)
150
150
  method_name = :"#{step.name.underscore}"
151
151
  raise "Invalid step name: #{step.name}\n Step names must not conflict with method names on Heya::Campaigns::Base" if respond_to?(method_name)
152
152
 
@@ -12,6 +12,13 @@ module Heya
12
12
  campaign_name.constantize.steps.find { |s| s.id == id }
13
13
  end
14
14
 
15
+ def initialize(id:, name:, campaign:, position:, action:, wait:, segment:, queue:, params: {})
16
+ super
17
+ if action.respond_to?(:validate_step)
18
+ action.validate_step(self)
19
+ end
20
+ end
21
+
15
22
  def gid
16
23
  to_gid(app: "heya").to_s
17
24
  end
@@ -19,6 +26,10 @@ module Heya
19
26
  def in_segment?(user)
20
27
  Heya.in_segments?(user, *campaign.__segments, segment)
21
28
  end
29
+
30
+ def campaign_name
31
+ @campaign_name ||= campaign.name
32
+ end
22
33
  end
23
34
  end
24
35
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Heya
4
- VERSION = "0.2.1"
4
+ VERSION = "0.3.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: heya
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua Wood
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-23 00:00:00.000000000 Z
11
+ date: 2020-06-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -58,9 +58,9 @@ dependencies:
58
58
  - - ">="
59
59
  - !ruby/object:Gem::Version
60
60
  version: '0'
61
- description: Heya is a customer communication and automation framework for Ruby on
62
- Rails. It's as robust as the hosted alternatives, without the integration and compliance
63
- nightmare.
61
+ description: Heya is a campaign mailer for Rails. Think of it like ActionMailer, but
62
+ for timed email sequences. It can also perform other actions like sending a text
63
+ message.
64
64
  email:
65
65
  - josh@honeybadger.io
66
66
  executables: []