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 +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +49 -2
- data/lib/sequins.rb +2 -0
- data/lib/sequins/base.rb +6 -6
- data/lib/sequins/errors.rb +1 -0
- data/lib/sequins/sequence.rb +24 -40
- data/lib/sequins/sequence_builder.rb +7 -3
- data/lib/sequins/step.rb +3 -2
- data/lib/sequins/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 056e21b0bc192d4c206223492dde4f2e0b77f6e9
|
4
|
+
data.tar.gz: 994041d33fec1c90138ce71579e042dd57e144b5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ae876d988d4817e944b75ff1119f593cc43d10eb8efbaac3c023639044a0d07dbf7093fe0232009c269aa2098aef3a501e3b9f412e1b4f6fdb019610c2ab662
|
7
|
+
data.tar.gz: 7ae79622feb2eb4af69937592eeff9c04dcf6189c7c9ea234f33b7d3922b95d3834f9146a26bfa3a39051c79fc23b6793708c8160c2912ca19a9955b5eb98974
|
data/Gemfile.lock
CHANGED
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
|
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 `
|
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
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
|
data/lib/sequins/errors.rb
CHANGED
data/lib/sequins/sequence.rb
CHANGED
@@ -7,60 +7,42 @@ module Sequins
|
|
7
7
|
def initialize(klass)
|
8
8
|
@klass = klass
|
9
9
|
@steps = {}
|
10
|
-
@
|
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
|
20
|
-
@
|
17
|
+
def add_hook(stage, &block)
|
18
|
+
@hooks[stage] ||= []
|
19
|
+
@hooks[stage] << StepProxy.new({}, block)
|
21
20
|
end
|
22
21
|
|
23
|
-
def
|
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
|
36
|
-
|
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
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
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
|
55
|
-
@
|
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
|
-
|
62
|
-
|
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
|
-
|
99
|
-
|
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,
|
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.
|
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.
|
22
|
+
@seq.add_hook(:before_sequence, &block)
|
19
23
|
end
|
20
24
|
|
21
25
|
def after_sequence(&block)
|
22
|
-
@seq.
|
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
|
data/lib/sequins/version.rb
CHANGED
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.
|
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-
|
11
|
+
date: 2018-09-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: docile
|