transitionable 0.1.1 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 933fdeae6a75c7c493a085742ae3beae2743a188
4
- data.tar.gz: 12a92da1cdf7e2d9e55bdcbb0f1922f88036a9c0
3
+ metadata.gz: 952f7bc9e470346c073f9e6ea3a57dfe99cdd95c
4
+ data.tar.gz: c3160957e7b0ab4084c17ca8df4e23eb2ab53717
5
5
  SHA512:
6
- metadata.gz: aa9d445044fb373bd20ac7bc2e65c0a3cf2a3d1200e3c51c4b4b44acd5dd001e5f160c37f3fc03e4b591271f43faaee7cf3b9dd2a6f617dd6a381a15204d73a3
7
- data.tar.gz: 1a064aef3e18dc2632c145d39abd84908b29e5ac53137c51d804eba47cb42d26fecd53504c3aca754ca2a2c50595232e1c9ba1dda02d660d0296accef059c2c0
6
+ metadata.gz: 8179578162e736f2a85b4a24d0e8ad7f5d8b7662b0f4581ed8cf5cf962111d262e103d4867403a829e0aa5781fbdc5bbbc724f6f896c1cd06db1a68fb477fa39
7
+ data.tar.gz: 9dba3437433e2ffd449623790055c8427d3a343d6cc99bc0bfd1854ca13a6e2cb558fbacf567e685e137421def9f140328e952d3d6c63a2e09a598bce2fe460f
data/Gemfile.lock CHANGED
@@ -1,22 +1,27 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- transitionable (0.1.1)
4
+ transitionable (0.2.0)
5
5
  activesupport (~> 5.2)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- activesupport (5.2.0)
10
+ activesupport (5.2.1)
11
11
  concurrent-ruby (~> 1.0, >= 1.0.2)
12
12
  i18n (>= 0.7, < 2)
13
13
  minitest (~> 5.1)
14
14
  tzinfo (~> 1.1)
15
+ coderay (1.1.2)
15
16
  concurrent-ruby (1.0.5)
16
17
  diff-lcs (1.3)
17
- i18n (1.0.1)
18
+ i18n (1.1.1)
18
19
  concurrent-ruby (~> 1.0)
20
+ method_source (0.9.2)
19
21
  minitest (5.11.3)
22
+ pry (0.12.0)
23
+ coderay (~> 1.1.0)
24
+ method_source (~> 0.9.0)
20
25
  rake (10.5.0)
21
26
  rspec (3.8.0)
22
27
  rspec-core (~> 3.8.0)
@@ -40,6 +45,7 @@ PLATFORMS
40
45
 
41
46
  DEPENDENCIES
42
47
  bundler (~> 1.16)
48
+ pry
43
49
  rake (~> 10.0)
44
50
  rspec (~> 3.7)
45
51
  transitionable!
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  A convention-based state machine that complements your models without stealing the show.
4
4
 
5
+ Multiple state machines are supported.
6
+
5
7
  ## Installation
6
8
 
7
9
  Add this line to your application's Gemfile:
@@ -16,10 +18,12 @@ And then execute:
16
18
 
17
19
  ## Usage
18
20
 
21
+ ### Single state machine in model
22
+
19
23
  ```ruby
20
24
  class Event
21
25
 
22
- # Requires including class to define the following constants BEFORE including this module:
26
+ # By default, Transitionable assumes including class defines the following constants BEFORE including this module:
23
27
  #
24
28
  # * STATES
25
29
  # * TRANSITIONS
@@ -61,6 +65,63 @@ event.validate_transition!(target_state: 'new_state')
61
65
  # => returns true or raises Transitionable::InvalidStateTransition exception
62
66
  ```
63
67
 
68
+ ### Multiple state machines in model
69
+
70
+ ```ruby
71
+ class Event
72
+
73
+ DELIVERY_STATES = {
74
+ STAGED: 'staged',
75
+ STARTED: 'started',
76
+ COMPLETED: 'completed'
77
+ }.freeze
78
+
79
+ PREP_STATES = {
80
+ COOKING: 'cooking',
81
+ COOKED: 'cooked'
82
+ }.freeze
83
+
84
+ DELIVERY_TRANSITIONS = [
85
+ { from: DELIVERY_STATES[:STAGED], to: DELIVERY_STATES[:STARTED] },
86
+ { from: DELIVERY_STATES[:STARTED], to: DELIVERY_STATES[:COMPLETED] }
87
+ ].freeze
88
+
89
+ PREP_TRANSITIONS = [
90
+ { from: PREP_STATES[:COOKING], to: PREP_STATES[:COOKED] }
91
+ ]
92
+
93
+ include Transitionable
94
+
95
+ transition :delivery_state, DELIVERY_STATES, DELIVERY_TRANSITIONS
96
+ transition :prep_state, PREP_STATES, PREP_TRANSITIONS
97
+
98
+ end
99
+ ```
100
+
101
+ Provides the following helpers
102
+
103
+ ```ruby
104
+ event.staged?
105
+ event.started?
106
+ event.completed?
107
+ event.cooking?
108
+ event.cooked?
109
+ ```
110
+
111
+ Provides 2 validation methods
112
+
113
+ ```ruby
114
+ event.validate_transition(target_state: 'new_state')
115
+ # => returns true or false
116
+
117
+ event.validate_transition!(target_state: 'new_state')
118
+ # => returns true or raises Transitionable::InvalidStateTransition exception
119
+ ```
120
+
121
+ #### Important assumptions with multiple state machines:
122
+ * Each state must be unique across all state machines in the model. Otherwise, `InvalidStateTransition` exception will thrown as Transitionable attempts to define the same helper method multiple times.
123
+ * For the same reason, `"#{state}?"` must not be defined in your model for each of your state.
124
+
64
125
  ## Development
65
126
 
66
127
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -1,3 +1,3 @@
1
1
  module Transitionable
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -8,39 +8,56 @@ module Transitionable
8
8
 
9
9
  class InvalidStateTransition < StandardError
10
10
  def initialize(from_state, to_state)
11
- msg = "Can't transition from #{from_state} to #{to_state}."
11
+ msg = from_state ?
12
+ "Can't transition from #{from_state} to #{to_state}." :
13
+ "Can't transition to #{to_state}."
12
14
  super(msg)
13
15
  end
14
16
  end
15
17
 
16
18
  module ClassMethods
17
- attr_accessor :trans_column
18
-
19
- def transition(column)
20
- self.trans_column = column
21
- self::STATES.values.each do |this_state|
19
+ attr_accessor :state_machines
20
+
21
+ # This assumes states is a hash
22
+ def transition(name, states = self::STATES, transitions = self::TRANSITIONS)
23
+ self.state_machines ||= {}
24
+ self.state_machines[name] = { states: states.values, transitions: transitions }
25
+ self.state_machines[name][:states].each do |this_state|
26
+ raise 'Method already defined' if self.new.respond_to? this_state
22
27
  define_method "#{this_state}?" do
23
- transitionable_state == this_state
28
+ current_state_based_on(this_state) == this_state
24
29
  end
25
30
  end
26
31
  end
27
32
  end
28
33
 
29
- def transitionable_state
30
- self.send(self.class.trans_column)
31
- end
32
-
33
34
  def validate_transition!(target_state:)
35
+ current_state = current_state_based_on(target_state)
34
36
  unless validate_transition(target_state: target_state)
35
- raise InvalidStateTransition.new(transitionable_state, target_state)
37
+ raise InvalidStateTransition.new(current_state, target_state)
36
38
  end
37
39
  true
38
40
  end
39
41
 
40
42
  def validate_transition(target_state:)
41
- self.class::TRANSITIONS.detect do |transition|
42
- transition[:from] == transitionable_state && transition[:to] == target_state
43
- end.present? ? true : false
43
+ self.class.state_machines.each do |machine_name, machine|
44
+ next unless machine[:states].include?(target_state)
45
+ current_state = send(machine_name)
46
+ matched_transition = machine[:transitions].detect do |transition|
47
+ transition[:from] == current_state && transition[:to] == target_state
48
+ end
49
+ return matched_transition.present?
50
+ end
51
+ raise InvalidStateTransition.new(nil, target_state)
52
+ end
53
+
54
+ private
55
+
56
+ def current_state_based_on(target_state)
57
+ self.class.state_machines.each do |machine_name, machine|
58
+ return send(machine_name) if machine[:states].include?(target_state)
59
+ end
60
+ raise InvalidStateTransition.new(nil, target_state)
44
61
  end
45
62
 
46
63
  end
@@ -35,5 +35,6 @@ Gem::Specification.new do |spec|
35
35
  spec.add_development_dependency "bundler", "~> 1.16"
36
36
  spec.add_development_dependency "rake", "~> 10.0"
37
37
  spec.add_development_dependency "rspec", "~> 3.7"
38
+ spec.add_development_dependency 'pry'
38
39
  spec.add_dependency "activesupport", "~>5.2"
39
40
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: transitionable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - zino
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-09-02 00:00:00.000000000 Z
11
+ date: 2018-11-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.7'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: activesupport
57
71
  requirement: !ruby/object:Gem::Requirement