transitions_listener 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|