transitions_listener 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 +4 -4
- data/CHANGELOG.md +3 -0
- data/Gemfile.lock +1 -1
- data/README.md +32 -13
- data/lib/transitions_listener.rb +5 -7
- data/lib/transitions_listener/listener.rb +42 -13
- data/lib/transitions_listener/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 89990d2302710513e08eca9a6131e56e7ce160a51d6a2beee7e78d49671d1050
|
4
|
+
data.tar.gz: 4e1996531fd05f0ef6f1796a97776517a6462b22dcbf050a5e69a27bf245f195
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 273301a304e5a9c724ab99cbcdb9b71d7a610ee0f0ef1e8a35138f83a07a8835bd1c6bce130af8171f83161c5d00824c30ae2dbc6732a903297d82479190705b
|
7
|
+
data.tar.gz: 6a24b40fb750518661fe4e18e0cb7dceb93122cb18feeeca701a107711383ce836691744a5fdf411943e90a7b28e99cbfba9bc8ce123b370831646e8ec682c21
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -26,35 +26,54 @@ And then execute: ```bundle install```
|
|
26
26
|
class Article < ActiveRecord::Base
|
27
27
|
include TransitionsListener
|
28
28
|
listen_transitions :state do
|
29
|
-
after_transition active: :inactive do |article, transition|
|
29
|
+
after_transition from: :active, to: :inactive do |article, transition|
|
30
30
|
# article.send_inactive_email
|
31
31
|
end
|
32
|
-
before_transition any
|
32
|
+
before_transition from: any, to: :deleted do |article, transition|
|
33
33
|
# article.errors.add(:base, "not possible") if article.active_carts.any?
|
34
34
|
end
|
35
35
|
|
36
|
-
before_transition({ any
|
36
|
+
before_transition({ from: any, to: any }, if: :valid_article?, unless: :destroyed?, callback: :any_to_any_callback)
|
37
37
|
end
|
38
38
|
|
39
39
|
def any_to_any_callback
|
40
40
|
puts "any to any callback called"
|
41
41
|
end
|
42
|
+
|
43
|
+
def valid_article?
|
44
|
+
true
|
45
|
+
end
|
46
|
+
|
47
|
+
def destroyed?
|
48
|
+
false
|
49
|
+
end
|
42
50
|
end
|
43
51
|
```
|
44
52
|
|
45
53
|
## API
|
46
|
-
- ````listen_transitions(attr_name){block}````
|
47
|
-
|
48
|
-
|
49
|
-
-
|
50
|
-
|
54
|
+
- ````listen_transitions(attr_name){block}````
|
55
|
+
permit to define state transitions listener for a specific model attribute
|
56
|
+
|
57
|
+
- Before update
|
58
|
+
````before_transition(states, if: :action?, unless: :action?, callback: :action) { block }````
|
59
|
+
Permit to listen transitions before the new state is saved
|
60
|
+
* states: (Mandatory) State Transition(s) to listen for
|
61
|
+
* if: (Optional) Positive conditional action(s) to execute callback. Sample: ```if: :deleted? | if: [:deleted?, :ready?]```
|
62
|
+
* unless: (Optional) Negative conditional action(s) to execute callback. Sample: ```unless: :deleted? | unless: [:deleted?, :ready?]```
|
63
|
+
* callback: (Optional) Model method to be called as a callback (Will be overridden If block is defined)
|
64
|
+
|
65
|
+
- After update (Args are similar to before update)
|
66
|
+
````after_transition(states, if: :action?, unless: :action?, callback: :action){ block }````
|
67
|
+
permit to listen transitions after the new state was saved
|
68
|
+
|
51
69
|
|
52
70
|
States can be defined as the following:
|
53
|
-
- ```before_transition(any
|
54
|
-
- ```before_transition(any
|
55
|
-
- ```before_transition(:active
|
56
|
-
- ```before_transition(%i[active inactive]
|
57
|
-
- ```before_transition(active: :inactive, inactive: :deleted){}``` block will be called when attr value is changed from :active to :inactive or :inactive to :deleted
|
71
|
+
- ```before_transition(from: any, to: any){}``` block will be called when attr value is changed from any value to any value
|
72
|
+
- ```before_transition(from: any, to: :active){}``` block will be called when attr value is changed from any value to :active
|
73
|
+
- ```before_transition(from: :active, to: any){}``` block will be called when attr value is changed from :active value to any value
|
74
|
+
- ```before_transition(from: %i[active inactive], to: %i[deleted cancelled]){}``` block will be called when attr value is changed from :active or inactive to :deleted or :cancelled
|
75
|
+
- ```before_transition([{ from: :active, to: :inactive }, { from: :inactive: :deleted }]){}``` block will be called when attr value is changed from :active to :inactive or :inactive to :deleted
|
76
|
+
- ```before_transition([{ active: :inactive, inactive: :deleted }]){}``` block will be called when attr value is changed from :active to :inactive or :inactive to :deleted (Shorter state definitions. Same as above)
|
58
77
|
|
59
78
|
## Development
|
60
79
|
|
data/lib/transitions_listener.rb
CHANGED
@@ -24,13 +24,11 @@ module TransitionsListener
|
|
24
24
|
|
25
25
|
def perform_transition_listeners(model, kind = :before)
|
26
26
|
transition_listeners.each do |listener|
|
27
|
-
|
28
|
-
listener.filter_transitions(kind,
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
model.public_send(transition[:block])
|
33
|
-
end
|
27
|
+
c_trans = current_transition_for(model, listener.attr)
|
28
|
+
listener.filter_transitions(kind, model, c_trans).each do |trans|
|
29
|
+
block = trans[:args][:callback]
|
30
|
+
args = c_trans.dup.merge(trans)
|
31
|
+
block.is_a?(Proc) ? block.call(model, args) : model.public_send(block)
|
34
32
|
end
|
35
33
|
end
|
36
34
|
end
|
@@ -8,30 +8,55 @@ module TransitionsListener
|
|
8
8
|
instance_eval(&block)
|
9
9
|
end
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
# @param states: (Array) Array of transitions [{ from:, to: }, {}, ...]
|
12
|
+
# Multiple transitions: [{ from: [..], to: [..] }, ...]
|
13
|
+
# Single transitions: [{ from: :state, to: :new_state }, ...]
|
14
|
+
# Single transition: { from: :state, to: :new_state }
|
15
|
+
# @param args (Hash): { callback: nil, if: nil, unless: nil }
|
16
|
+
# callback: (Sym) Method name to be used as the callback
|
17
|
+
# if: (Sym) conditional methods
|
18
|
+
# else: (Sym) conditional methods
|
19
|
+
def before_transition(states, args = {}, &block)
|
20
|
+
args[:callback] ||= block if block
|
21
|
+
before_transitions(states: parse_states(states), args: args)
|
13
22
|
end
|
14
23
|
|
15
|
-
|
16
|
-
|
24
|
+
# @param states (Array): Same as before transitions
|
25
|
+
# @param args (Hash): Same as before args
|
26
|
+
def after_transition(states, args = {}, &block)
|
27
|
+
args[:callback] ||= block if block
|
28
|
+
after_transitions(states: parse_states(states), args: args)
|
17
29
|
end
|
18
30
|
|
19
|
-
def filter_transitions(kind, from:, to:)
|
31
|
+
def filter_transitions(kind, model, from:, to:)
|
20
32
|
transitions = kind == :before ? before_transitions : after_transitions
|
21
33
|
transitions.select do |transition|
|
22
|
-
|
34
|
+
match_conditions?(model, transition) &&
|
35
|
+
match_states?(transition, from, to)
|
23
36
|
end
|
24
37
|
end
|
25
38
|
|
26
39
|
private
|
27
40
|
|
28
|
-
def match_states?(
|
29
|
-
|
41
|
+
def match_states?(transition, from_state, to_state)
|
42
|
+
transition[:states].any? do |state|
|
43
|
+
t_from = state[:from]
|
44
|
+
t_to = state[:to]
|
30
45
|
(t_from == [any] || t_from.include?(from_state.to_s)) &&
|
31
46
|
(t_to == [any] || t_to.include?(to_state.to_s))
|
32
47
|
end
|
33
48
|
end
|
34
49
|
|
50
|
+
def match_conditions?(model, transition)
|
51
|
+
args = transition[:args]
|
52
|
+
yes_actions = Array(args[:if])
|
53
|
+
no_actions = Array(args[:unless])
|
54
|
+
return false unless yes_actions.all? { |action| model.send(action) }
|
55
|
+
return false unless no_actions.all? { |action| !model.send(action) }
|
56
|
+
|
57
|
+
true
|
58
|
+
end
|
59
|
+
|
35
60
|
def any
|
36
61
|
'any_transition_key'
|
37
62
|
end
|
@@ -49,11 +74,15 @@ module TransitionsListener
|
|
49
74
|
end
|
50
75
|
|
51
76
|
def parse_states(states)
|
52
|
-
states.
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
77
|
+
is_shorter_definition = states.is_a?(Hash) && !states[:from]
|
78
|
+
states = states.map { |k, v| { from: k, to: v } } if is_shorter_definition
|
79
|
+
is_single_definition = !states.is_a?(Array)
|
80
|
+
states = [states] if is_single_definition
|
81
|
+
states.map do |trans|
|
82
|
+
from = Array(trans[:from]).map(&:to_s)
|
83
|
+
to = Array(trans[:to]).map(&:to_s)
|
84
|
+
{ from: from, to: to }
|
85
|
+
end
|
57
86
|
end
|
58
87
|
end
|
59
88
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: transitions_listener
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Owen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-05-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|