sequins 0.1.1 → 0.1.2

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
  SHA1:
3
- metadata.gz: 4262d19a9cf34f35abf9368c79c98c496a6e84a9
4
- data.tar.gz: a7dce47d5edd4c0f1c6091b2f55fba96c0bc58fd
3
+ metadata.gz: 056e21b0bc192d4c206223492dde4f2e0b77f6e9
4
+ data.tar.gz: 994041d33fec1c90138ce71579e042dd57e144b5
5
5
  SHA512:
6
- metadata.gz: 481a85ea6424756081c5c23ba00f7f5284cfc880b252725b558d7a9ecceebfa5f8b4da4b6d2a4ab4f9998bfca4c6f430956d15dfbbe8caaaff455ca55580905f
7
- data.tar.gz: b6256a9b9989104f070fde84cf3f2482170f834bb0ff055695e18a5aa4360718f33105cdd72308dac5e8998832839cadedddf83f2441225d200b3fde01625c51
6
+ metadata.gz: 1ae876d988d4817e944b75ff1119f593cc43d10eb8efbaac3c023639044a0d07dbf7093fe0232009c269aa2098aef3a501e3b9f412e1b4f6fdb019610c2ab662
7
+ data.tar.gz: 7ae79622feb2eb4af69937592eeff9c04dcf6189c7c9ea234f33b7d3922b95d3834f9146a26bfa3a39051c79fc23b6793708c8160c2912ca19a9955b5eb98974
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sequins (0.1.0)
4
+ sequins (0.1.1)
5
5
  autoloaded (~> 2)
6
6
  docile
7
7
  rails (>= 5.0)
data/README.md CHANGED
@@ -42,13 +42,59 @@ class ExampleSequence < Sequins::Base
42
42
  end
43
43
  ```
44
44
 
45
+ ### Steps
46
+
47
+ A step is a Ruby block. It has the following attributes available:
48
+
49
+ * `target` is the target object that you pass into `trigger` or `run_step_for_target`
50
+ * `step_name` is the step that's currently running
51
+ * `sequence` is an instance of `Sequins::Sequence`. From this you have access to the sequence class via `sequence.klass`
52
+
53
+ You also have direct access to class methods on your `Sequence::Base` subclass. For example:
54
+
55
+ ```ruby
56
+ class Example2Sequence < Sequins::Base
57
+ sequence do
58
+ step :start, initial: true do
59
+ send_message target, "hi there"
60
+ end
61
+ end
62
+
63
+ def self.send_message(target, text)
64
+ SomeMailer.send_message(target.id, text).deliver_later
65
+ end
66
+ end
67
+ ```
68
+
69
+ You can also send arguments to `trigger` or `run_step_for_target` which will be passed as block arguments. Example:
70
+
71
+ ```ruby
72
+ class Example3Sequence < Sequins::Base
73
+ sequence do
74
+ step :start, initial: true do |something|
75
+ if something.present?
76
+ delay 3.days, then: :next_step
77
+ else
78
+ end_sequence
79
+ end
80
+ end
81
+
82
+ step :next_step do
83
+ # something interesting
84
+ end
85
+ end
86
+ end
87
+
88
+ Example3Sequence.trigger(User.first, "this will trigger a delay")
89
+ ```
90
+
45
91
  ### Delay Options
46
92
 
47
93
  The first argument to `delay` is always an interval, usually expressed as a number of days. Ex: `3.days`.
48
94
  In addition, it can take these arguments:
49
95
 
50
96
  * `then` (always required) this tells delay which step to run next
51
- * `at` specifies a time relative to the user's local timezone to run the next step
97
+ * `at` specifies a time relative to the target's local timezone to run the next step
52
98
  * `only` limits what days to send on. Currently the only valid option is `:weekdays`
53
99
 
54
100
  ### Trigger a Sequence
@@ -66,11 +112,12 @@ Sequences can define hooks. The available hooks are:
66
112
 
67
113
  ```
68
114
  before_each_step # runs before every step.
115
+ after_each_step # runs after each step
69
116
  before_sequence # runs before the sequence starts.
70
117
  after_sequence # runs after the sequence ends with an explicit `end_sequence`
71
118
  ```
72
119
 
73
- Hooks are run in the same way steps are, so you have access to the `user` object if you want it.
120
+ Hooks are run in the same way steps are, so you have access to all of the same attributes as a step. Within `before_each_step` and `after_each_step`, `step_name` will be set to the step that is about to or just finished running. Within `before_sequence` and `after_sequence` `step_name` has no meaning.
74
121
 
75
122
  ## Configuration
76
123
 
data/lib/sequins.rb CHANGED
@@ -24,3 +24,5 @@ module Sequins
24
24
  yield configuration
25
25
  end
26
26
  end
27
+
28
+ require 'sequins/errors'
data/lib/sequins/base.rb CHANGED
@@ -13,16 +13,16 @@ module Sequins
13
13
  self.to_s.underscore.gsub(/_sequence$/, '')
14
14
  end
15
15
 
16
- def self.trigger(target)
17
- sequence.trigger(target)
16
+ def self.trigger(target, *args)
17
+ sequence.trigger(target, *args)
18
18
  end
19
19
 
20
- def trigger(target)
21
- self.class.trigger(target)
20
+ def trigger(target, *args)
21
+ self.class.trigger(target, *args)
22
22
  end
23
23
 
24
- def run_step_for_target(step_name, target)
25
- self.class.sequence.run_step_for_target(step_name, target)
24
+ def run_step_for_target(step_name, target, *args)
25
+ self.class.sequence.run_step_for_target(step_name, target, *args)
26
26
  end
27
27
  end
28
28
  end
@@ -1,4 +1,5 @@
1
1
  module Sequins
2
2
  class UnknownStepError < StandardError; end
3
+ class NoInitialStepError < StandardError; end
3
4
  end
4
5
 
@@ -7,60 +7,42 @@ module Sequins
7
7
  def initialize(klass)
8
8
  @klass = klass
9
9
  @steps = {}
10
- @before_each_step_hooks = []
11
- @before_sequence_hooks = []
12
- @after_sequence_hooks = []
10
+ @hooks = {}
13
11
  end
14
12
 
15
13
  def add_step(name, options={}, &block)
16
14
  @steps[name] = StepProxy.new(options, block)
17
15
  end
18
16
 
19
- def add_before_each_step_hook(&block)
20
- @before_each_step_hooks << StepProxy.new({}, block)
17
+ def add_hook(stage, &block)
18
+ @hooks[stage] ||= []
19
+ @hooks[stage] << StepProxy.new({}, block)
21
20
  end
22
21
 
23
- def add_before_sequence_hook(&block)
24
- @before_sequence_hooks << StepProxy.new({}, block)
25
- end
26
-
27
- def add_after_sequence_hook(&block)
28
- @after_sequence_hooks << StepProxy.new({}, block)
29
- end
30
-
31
- def run_step_for_target(step_name, target)
22
+ def run_step_for_target(step_name, target, *args)
32
23
  proxy = @steps[step_name]
33
24
  raise UnknownStepError.new(step_name) if proxy.nil?
34
25
 
35
- unless run_before_each_step_hooks_for_target(target)
36
- run_after_sequence_hooks_for_target(target)
26
+ unless run_hooks_for_target(:before_each_step, target, step_name)
27
+ run_hooks_for_target(:after_sequence, target, :_after_sequence)
37
28
  return false
38
29
  end
39
30
 
40
- step = Docile.dsl_eval(Step.new(target, self), &(proxy.block))
41
- if step.sequence_ended?
42
- run_after_sequence_hooks_for_target(target)
43
- return false
44
- end
45
- end
31
+ step = Docile.dsl_eval(Step.new(target, self, step_name), args, &(proxy.block))
46
32
 
47
- def run_before_each_step_hooks_for_target(target)
48
- @before_each_step_hooks.each do |hook|
49
- step = Docile.dsl_eval(Step.new(target, self), &(hook.block))
50
- return false if step.sequence_ended?
33
+ ended_after_each = !run_hooks_for_target(:after_each_step, target, step_name)
34
+
35
+ if step.sequence_ended? || ended_after_each
36
+ run_hooks_for_target(:after_sequence, target, :_after_sequence)
37
+ return false
51
38
  end
52
39
  end
53
40
 
54
- def run_before_sequence_hooks_for_target(target)
55
- @before_sequence_hooks.each do |hook|
56
- step = Docile.dsl_eval(Step.new(target, self), &(hook.block))
57
- return false if step.sequence_ended?
58
- end
59
- end
41
+ def run_hooks_for_target(stage, target, step_name)
42
+ return if @hooks[stage].nil? || @hooks[stage].empty?
60
43
 
61
- def run_after_sequence_hooks_for_target(target)
62
- @after_sequence_hooks.each do |hook|
63
- step = Docile.dsl_eval(Step.new(target, self), &(hook.block))
44
+ @hooks[stage].each do |hook|
45
+ step = Docile.dsl_eval(Step.new(target, self, step_name), &(hook.block))
64
46
  return false if step.sequence_ended?
65
47
  end
66
48
  end
@@ -94,14 +76,16 @@ module Sequins
94
76
  Sequins::DelayWorker.set(wait_until: delay_until).perform_later(@klass.to_s, target.class.to_s, target.id, next_step.to_s)
95
77
  end
96
78
 
97
- def trigger(target)
98
- unless run_before_sequence_hooks_for_target(target)
99
- run_after_sequence_hooks_for_target(target)
79
+ def trigger(target, *args)
80
+ step_name, _ = @steps.detect { |_, s| s.options[:initial] }
81
+ raise NoInitialStepError.new unless step_name.present?
82
+
83
+ unless run_hooks_for_target(:before_sequence, target, :_before_sequence)
84
+ run_hooks_for_target(:after_sequence, target, :_after_sequence)
100
85
  return false
101
86
  end
102
87
 
103
- step_name, _ = @steps.detect { |_, s| s.options[:initial] }
104
- run_step_for_target(step_name, target)
88
+ run_step_for_target(step_name, target, *args)
105
89
  end
106
90
 
107
91
  end
@@ -11,15 +11,19 @@ module Sequins
11
11
  end
12
12
 
13
13
  def before_each_step(&block)
14
- @seq.add_before_each_step_hook(&block)
14
+ @seq.add_hook(:before_each_step, &block)
15
+ end
16
+
17
+ def after_each_step(&block)
18
+ @seq.add_hook(:after_each_step, &block)
15
19
  end
16
20
 
17
21
  def before_sequence(&block)
18
- @seq.add_before_sequence_hook(&block)
22
+ @seq.add_hook(:before_sequence, &block)
19
23
  end
20
24
 
21
25
  def after_sequence(&block)
22
- @seq.add_after_sequence_hook(&block)
26
+ @seq.add_hook(:after_sequence, &block)
23
27
  end
24
28
 
25
29
  def build
data/lib/sequins/step.rb CHANGED
@@ -1,10 +1,11 @@
1
1
  module Sequins
2
2
  class Step
3
- attr_reader :target
3
+ attr_reader :target, :step_name
4
4
 
5
- def initialize(target, sequence)
5
+ def initialize(target, sequence, step_name)
6
6
  @target = target
7
7
  @sequence = sequence
8
+ @step_name = step_name
8
9
  end
9
10
 
10
11
  def end_sequence
@@ -1,3 +1,3 @@
1
1
  module Sequins
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequins
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pete Keen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-08-23 00:00:00.000000000 Z
11
+ date: 2018-09-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: docile