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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b80f1e14787d8e9fb36dbecdf16ab61ee0af545aad73e6eb6264ed88a676187c
4
- data.tar.gz: dbb6ec94ee53192ed571d61467a0805d3e67369953033fd1461ba89460a60a9c
3
+ metadata.gz: 89990d2302710513e08eca9a6131e56e7ce160a51d6a2beee7e78d49671d1050
4
+ data.tar.gz: 4e1996531fd05f0ef6f1796a97776517a6462b22dcbf050a5e69a27bf245f195
5
5
  SHA512:
6
- metadata.gz: a576d7536337cbfeea23b48061d974f3670cf9002dfc3fb0b05bc1e52daa1739e1fdb3775c2331eb96dd83c5227ca90be4d544d6a5c2141435a986acd8a4a31d
7
- data.tar.gz: 455b5e5d04dc184f769c4afe3e29c808488cc7eb5815667f14411015cccd8e655dcc2bd8d20bfd78659d5c37be91fc2148eacf23aa3c16a73eeb3fd1fa62b5c9
6
+ metadata.gz: 273301a304e5a9c724ab99cbcdb9b71d7a610ee0f0ef1e8a35138f83a07a8835bd1c6bce130af8171f83161c5d00824c30ae2dbc6732a903297d82479190705b
7
+ data.tar.gz: 6a24b40fb750518661fe4e18e0cb7dceb93122cb18feeeca701a107711383ce836691744a5fdf411943e90a7b28e99cbfba9bc8ce123b370831646e8ec682c21
@@ -1,3 +1,6 @@
1
+ # Release 0.3.0 (May 5, 2020)
2
+ - reformat: reformat state definitions to define using from:, to: (more understandable)
3
+
1
4
  # Release 0.2.1 (April 24, 2020)
2
5
  - Method callback does not receive transition info
3
6
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- transitions_listener (0.2.1)
4
+ transitions_listener (0.3.0)
5
5
  activerecord
6
6
  activesupport
7
7
 
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 => :deleted do |article, transition|
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 => any }, :any_to_any_callback)
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}```` permit to define state transitions listener for a specific model attribute
47
- - ````before_transition(states){block}```` permit to listen transitions before the new state is saved (Before update)
48
- - ````after_transition(states){block}```` permit to listen transitions after the new state was saved (After update)
49
- - ````before_transition(states, :callback_name)```` model method to listen transition callbacks
50
- - ````after_transition(states, :callback_name)```` model method to listen transition callbacks
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 => any){}``` block will be called when attr value is changed from any value to any value
54
- - ```before_transition(any => :active){}``` block will be called when attr value is changed from any value to :active
55
- - ```before_transition(:active => any){}``` block will be called when attr value is changed from :active value to any value
56
- - ```before_transition(%i[active inactive] => %i[deleted cancelled]){}``` block will be called when attr value is changed from :active or inactive to :deleted or :cancelled
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
 
@@ -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
- c_transition = current_transition_for(model, listener.attr)
28
- listener.filter_transitions(kind, c_transition).each do |transition|
29
- if transition[:block].is_a?(Proc)
30
- transition[:block].call(model, c_transition.merge(transition))
31
- else # method name
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
- def before_transition(states, callback_method = nil, &block)
12
- before_transitions(states: states, block: callback_method || block)
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
- def after_transition(states, callback_method = nil, &block)
16
- after_transitions(states: states, block: callback_method || block)
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
- match_states?(transition[:states], from, to)
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?(states, from_state, to_state)
29
- parse_states(states).any? do |t_from, t_to|
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.map do |from, to|
53
- from = [from] unless from.is_a? Array
54
- to = [to] unless to.is_a? Array
55
- [from.map(&:to_s), to.map(&:to_s)]
56
- end.to_h
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TransitionsListener
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: transitions_listener
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
  - Owen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-04-24 00:00:00.000000000 Z
11
+ date: 2020-05-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord