stateful.rb 1.0.2 → 2.0.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
  SHA256:
3
- metadata.gz: 2839c6d2a810cc8c40ec569ca293893fbcbf352639ff93058ad4d8f0025987ed
4
- data.tar.gz: 2cbc8fb5a317f8413b67f1ef6231b07271f7b8290200adefea935a3dd3e37c5d
3
+ metadata.gz: 5da7e8a527bd572e70442a09736ecd50fb6a16b4d3d9b6b23ccddf0630919b7b
4
+ data.tar.gz: 0254fcbc662dabddb91a94891c55f6e786d6b990845b15bdfebd1aa1a94e65c5
5
5
  SHA512:
6
- metadata.gz: 2bf9318595ad13640e2b03855b8279faf5cd3e4183685c0eacfa72fb9756ae9e79f501ef9332e6115e744da6fc4b2f7434e09ef87b0be60ab6a8ba0990048f91
7
- data.tar.gz: 6043e90aa8571a6328ddc62b902f77f8e448693eeb5248edcb22ab0de1e38a007772b7b0acc6f213e0ec5ab7d479cbf4a9da5e399df095e68594d8230d5e0573
6
+ metadata.gz: 8832fda98fcdedd0a931c7822d6144026ca053f79b840b6f28845bddb8e1bbfe14f5bf55ccf5e5389ea3d0d78b4ac38dc1d79311eaaebd1c47d1667aba565038
7
+ data.tar.gz: 30fa4829c8979de205b41c65174e4e033e00efbc7923b9dcb0b4e90ef1cb6f91eb6188783341bdc24ce4eec069b20ebe587a67dc24a617293fb7c7053f08b754
@@ -4,9 +4,7 @@
4
4
  module Stateful
5
5
  module ActiveRecord
6
6
  module ClassMethods
7
-
8
7
  class << self
9
-
10
8
  def extended(klass)
11
9
  klass.define_stateful_column_name_setter_method
12
10
  klass.define_stateful_column_name_getter_method
@@ -15,9 +13,17 @@ module Stateful
15
13
  klass.define_initial_stateQ_method
16
14
  klass.define_final_stateQ_method
17
15
  end
18
-
19
16
  end # class << self
20
17
 
18
+ def define_named_machine_methods(machine_name)
19
+ define_stateful_column_name_setter_method(machine_name: machine_name)
20
+ define_stateful_column_name_getter_method(machine_name: machine_name)
21
+ define_next_state_method(machine_name: machine_name)
22
+ define_transitions_method(machine_name: machine_name)
23
+ define_initial_stateQ_method(machine_name: machine_name)
24
+ define_final_stateQ_method(machine_name: machine_name)
25
+ end
26
+
21
27
  def stateful_column_name=(stateful_column_name)
22
28
  @stateful_column_name = stateful_column_name
23
29
  end
@@ -26,75 +32,86 @@ module Stateful
26
32
  @stateful_column_name
27
33
  end
28
34
 
29
- def define_event_method(transition)
30
- stateful_column_name = self.instance_variable_get(:@stateful_column_name)
35
+ def column_name_for_machine(machine_name = nil)
36
+ if machine_name
37
+ "#{machine_name}_state"
38
+ else
39
+ instance_variable_get(:@stateful_column_name)
40
+ end
41
+ end
42
+
43
+ def define_event_method(transition, machine_name: nil)
44
+ stateful_column_name = column_name_for_machine(machine_name)
31
45
  define_method(transition.event_name) do
32
46
  next_state_name = self.send(stateful_column_name).next_state_name(transition.event_name)
33
- next_state = self.class.stateful_states.find(next_state_name)
47
+ next_state = self.class.stateful_state_machine(machine_name).find(next_state_name)
34
48
  self.send("#{stateful_column_name}=", next_state)
35
49
  end
36
50
  end
37
51
 
38
- def define_status_predicate_method(state_name)
39
- stateful_column_name = self.instance_variable_get(:@stateful_column_name)
52
+ def define_status_predicate_method(state_name, machine_name: nil)
53
+ stateful_column_name = column_name_for_machine(machine_name)
40
54
  define_method("#{state_name}?") do
41
55
  self.send(stateful_column_name).name == state_name
42
56
  end
43
57
  end
44
58
 
45
- def define_stateful_column_name_setter_method
46
- stateful_column_name = self.instance_variable_get(:@stateful_column_name)
59
+ def define_stateful_column_name_setter_method(machine_name: nil)
60
+ stateful_column_name = column_name_for_machine(machine_name)
47
61
  define_method("#{stateful_column_name}=") do |state|
48
- instance_variable_set("@#{stateful_column_name}", self.class.stateful_states.find(state))
62
+ instance_variable_set("@#{stateful_column_name}", self.class.stateful_state_machine(machine_name).find(state))
49
63
  write_attribute(stateful_column_name, instance_variable_get("@#{stateful_column_name}").name)
50
64
  self.save
51
65
  instance_variable_get("@#{stateful_column_name}")
52
66
  end
53
67
  end
54
68
 
55
- def define_stateful_column_name_getter_method
56
- stateful_column_name = self.instance_variable_get(:@stateful_column_name)
69
+ def define_stateful_column_name_getter_method(machine_name: nil)
70
+ stateful_column_name = column_name_for_machine(machine_name)
57
71
  define_method(stateful_column_name) do
58
- instance_variable_set("@#{stateful_column_name}", self.class.stateful_states.find(read_attribute(stateful_column_name)))
72
+ instance_variable_set("@#{stateful_column_name}", self.class.stateful_state_machine(machine_name).find(read_attribute(stateful_column_name)))
59
73
  if state = instance_variable_get("@#{stateful_column_name}")
60
74
  state
61
75
  else
62
- initial_state = self.class.stateful_states.initial_state
76
+ initial_state = self.class.stateful_state_machine(machine_name).initial_state
63
77
  self.send("#{stateful_column_name}=", initial_state.name)
64
78
  initial_state
65
79
  end
66
80
  end
67
81
  end
68
82
 
69
- def define_next_state_method
70
- stateful_column_name = self.instance_variable_get(:@stateful_column_name)
71
- define_method(:next_state) do |event_name|
83
+ def define_next_state_method(machine_name: nil)
84
+ stateful_column_name = column_name_for_machine(machine_name)
85
+ method_name = machine_name ? "#{machine_name}_next_state" : :next_state
86
+ define_method(method_name) do |event_name|
72
87
  next_state_name = self.send(stateful_column_name).next_state_name(event_name)
73
- all_states.find(next_state_name)
88
+ self.class.stateful_state_machine(machine_name).find(next_state_name)
74
89
  end
75
90
  end
76
91
 
77
- def define_transitions_method
78
- stateful_column_name = self.instance_variable_get(:@stateful_column_name)
79
- define_method(:transitions) do
92
+ def define_transitions_method(machine_name: nil)
93
+ stateful_column_name = column_name_for_machine(machine_name)
94
+ method_name = machine_name ? "#{machine_name}_transitions" : :transitions
95
+ define_method(method_name) do
80
96
  self.send(stateful_column_name).transitions
81
97
  end
82
98
  end
83
99
 
84
- def define_initial_stateQ_method
85
- stateful_column_name = self.instance_variable_get(:@stateful_column_name)
86
- define_method(:initial_state?) do
87
- self.send(stateful_column_name) == initial_state
100
+ def define_initial_stateQ_method(machine_name: nil)
101
+ stateful_column_name = column_name_for_machine(machine_name)
102
+ method_name = machine_name ? "#{machine_name}_initial_state?" : :initial_state?
103
+ define_method(method_name) do
104
+ self.send(stateful_column_name) == self.class.stateful_state_machine(machine_name).initial_state
88
105
  end
89
106
  end
90
107
 
91
- def define_final_stateQ_method
92
- stateful_column_name = self.instance_variable_get(:@stateful_column_name)
93
- define_method(:final_state?) do
94
- final_states.include?(self.send(stateful_column_name))
108
+ def define_final_stateQ_method(machine_name: nil)
109
+ stateful_column_name = column_name_for_machine(machine_name)
110
+ method_name = machine_name ? "#{machine_name}_final_state?" : :final_state?
111
+ define_method(method_name) do
112
+ self.class.stateful_state_machine(machine_name).final_states.include?(self.send(stateful_column_name))
95
113
  end
96
114
  end
97
-
98
115
  end
99
116
  end
100
117
  end
@@ -1,35 +1,52 @@
1
1
  # Stateful/ClassMethods.rb
2
2
  # Stateful::ClassMethods
3
3
 
4
- require_relative 'States'
4
+ require_relative 'StateMachine'
5
5
 
6
6
  module Stateful
7
7
  module ClassMethods
8
+ def state_machines
9
+ @state_machines ||= {}
10
+ end
8
11
 
9
- def stateful_states
10
- @stateful_states ||= Stateful::States.new(self)
12
+ def stateful_state_machine(machine_name = nil)
13
+ if machine_name
14
+ state_machines[machine_name] ||= Stateful::StateMachine.new(self, machine_name: machine_name)
15
+ else
16
+ @stateful_state_machine ||= Stateful::StateMachine.new(self)
17
+ end
11
18
  end
12
19
 
13
20
  # start DSL
14
21
 
15
22
  def stateful(options = {}, &block)
16
- stateful_states.stateful(options, &block)
23
+ stateful_state_machine.options = options unless options.empty?
24
+ class_eval(&block) if block
25
+ end
26
+
27
+ def state_machine(name, options = {}, &block)
28
+ unless state_machines.key?(name)
29
+ define_named_machine_methods(name)
30
+ end
31
+ sm = stateful_state_machine(name)
32
+ sm.options = options unless options.empty?
33
+ sm.instance_eval(&block) if block
17
34
  end
18
35
 
19
36
  def initial_state(state_name = nil, options = {}, &block)
20
- stateful_states.initial_state(state_name, options, &block)
37
+ stateful_state_machine.initial_state(state_name, options, &block)
21
38
  end
22
39
 
23
40
  def state(state_name, options = {}, &block)
24
- stateful_states.state(state_name, options, &block)
41
+ stateful_state_machine.state(state_name, options, &block)
25
42
  end
26
43
 
27
44
  def final_state(*state_names)
28
- stateful_states.final_state(*state_names)
45
+ stateful_state_machine.final_state(*state_names)
29
46
  end
30
47
 
31
48
  def final_states(*state_names)
32
- stateful_states.final_states(*state_names)
49
+ stateful_state_machine.final_states(*state_names)
33
50
  end
34
51
 
35
52
  # end DSL
@@ -37,9 +54,12 @@ module Stateful
37
54
  # predicate methods
38
55
 
39
56
  def final_state?
40
- !final_states.empty?
57
+ if state_machines.empty?
58
+ !final_states.empty?
59
+ else
60
+ state_machines.all?{|_name, states| !states.final_states.empty?}
61
+ end
41
62
  end
42
63
  alias_method :has_final_state?, :final_state?
43
-
44
64
  end
45
65
  end
@@ -3,28 +3,40 @@
3
3
 
4
4
  module Stateful
5
5
  module InstanceMethods
6
+ def state_machines
7
+ self.class.state_machines
8
+ end
9
+
10
+ def state_machine(name)
11
+ state_machines[name]
12
+ end
6
13
 
7
- def all_states
8
- self.class.stateful_states
14
+ def all_states(machine_name = nil)
15
+ self.class.stateful_state_machine(machine_name)
9
16
  end
10
17
 
11
- def initial_state
12
- self.class.initial_state
18
+ def initial_state(machine_name = nil)
19
+ self.class.stateful_state_machine(machine_name).initial_state
13
20
  end
14
21
 
15
- def final_state
16
- self.class.final_state
22
+ def final_state(machine_name = nil)
23
+ self.class.stateful_state_machine(machine_name).final_state
17
24
  end
18
25
 
19
- def final_states
20
- self.class.final_states
26
+ def final_states(machine_name = nil)
27
+ self.class.stateful_state_machine(machine_name).final_states
21
28
  end
22
29
 
23
30
  # predicate methods
24
31
 
25
- def active?
26
- !final_state?
32
+ def active?(machine_name = nil)
33
+ if machine_name
34
+ !send("#{machine_name}_final_state?")
35
+ elsif state_machines.empty?
36
+ !final_state?
37
+ else
38
+ state_machines.keys.any?{|name| !send("#{name}_final_state?")}
39
+ end
27
40
  end
28
-
29
41
  end
30
42
  end
@@ -4,9 +4,7 @@
4
4
  module Stateful
5
5
  module Poro
6
6
  module ClassMethods
7
-
8
7
  class << self
9
-
10
8
  def extended(klass)
11
9
  klass.define_stateful_variable_name_setter_method
12
10
  klass.define_stateful_variable_name_getter_method
@@ -15,9 +13,17 @@ module Stateful
15
13
  klass.define_initial_stateQ_method
16
14
  klass.define_final_stateQ_method
17
15
  end
18
-
19
16
  end # class << self
20
17
 
18
+ def define_named_machine_methods(machine_name)
19
+ define_stateful_variable_name_setter_method(machine_name: machine_name)
20
+ define_stateful_variable_name_getter_method(machine_name: machine_name)
21
+ define_next_state_method(machine_name: machine_name)
22
+ define_transitions_method(machine_name: machine_name)
23
+ define_initial_stateQ_method(machine_name: machine_name)
24
+ define_final_stateQ_method(machine_name: machine_name)
25
+ end
26
+
21
27
  def stateful_variable_name=(stateful_variable_name)
22
28
  @stateful_variable_name = stateful_variable_name
23
29
  end
@@ -26,71 +32,82 @@ module Stateful
26
32
  @stateful_variable_name
27
33
  end
28
34
 
29
- def define_event_method(transition)
30
- stateful_variable_name = self.instance_variable_get(:@stateful_variable_name)
35
+ def variable_name_for_machine(machine_name = nil)
36
+ if machine_name
37
+ "#{machine_name}_state"
38
+ else
39
+ instance_variable_get(:@stateful_variable_name)
40
+ end
41
+ end
42
+
43
+ def define_event_method(transition, machine_name: nil)
44
+ variable_name = variable_name_for_machine(machine_name)
31
45
  define_method(transition.event_name) do
32
- next_state_name = self.send(stateful_variable_name).next_state_name(transition.event_name)
33
- next_state = self.class.stateful_states.find(next_state_name)
34
- self.send("#{stateful_variable_name}=", next_state)
46
+ next_state_name = self.send(variable_name).next_state_name(transition.event_name)
47
+ next_state = self.class.stateful_state_machine(machine_name).find(next_state_name)
48
+ self.send("#{variable_name}=", next_state)
35
49
  end
36
50
  end
37
51
 
38
- def define_status_predicate_method(state_name)
39
- stateful_variable_name = self.instance_variable_get(:@stateful_variable_name)
52
+ def define_status_predicate_method(state_name, machine_name: nil)
53
+ variable_name = variable_name_for_machine(machine_name)
40
54
  define_method("#{state_name}?") do
41
- self.send(stateful_variable_name).name == state_name
55
+ self.send(variable_name).name == state_name
42
56
  end
43
57
  end
44
58
 
45
- def define_stateful_variable_name_setter_method
46
- stateful_variable_name = self.instance_variable_get(:@stateful_variable_name)
47
- define_method("#{stateful_variable_name}=") do |state|
48
- instance_variable_set("@#{stateful_variable_name}", self.class.stateful_states.find(state))
59
+ def define_stateful_variable_name_setter_method(machine_name: nil)
60
+ variable_name = variable_name_for_machine(machine_name)
61
+ define_method("#{variable_name}=") do |state|
62
+ instance_variable_set("@#{variable_name}", self.class.stateful_state_machine(machine_name).find(state))
49
63
  end
50
64
  end
51
65
 
52
- def define_stateful_variable_name_getter_method
53
- stateful_variable_name = self.instance_variable_get(:@stateful_variable_name)
54
- define_method(stateful_variable_name) do
55
- if state = instance_variable_get("@#{stateful_variable_name}")
66
+ def define_stateful_variable_name_getter_method(machine_name: nil)
67
+ variable_name = variable_name_for_machine(machine_name)
68
+ define_method(variable_name) do
69
+ if state = instance_variable_get("@#{variable_name}")
56
70
  state
57
71
  else
58
- initial_state = self.class.stateful_states.initial_state
59
- self.send("#{stateful_variable_name}=", initial_state.name)
72
+ initial_state = self.class.stateful_state_machine(machine_name).initial_state
73
+ self.send("#{variable_name}=", initial_state.name)
60
74
  initial_state
61
75
  end
62
76
  end
63
77
  end
64
78
 
65
- def define_next_state_method
66
- stateful_variable_name = self.instance_variable_get(:@stateful_variable_name)
67
- define_method(:next_state) do |event_name|
68
- next_state_name = self.send(stateful_variable_name).next_state_name(event_name)
69
- all_states.find(next_state_name)
79
+ def define_next_state_method(machine_name: nil)
80
+ variable_name = variable_name_for_machine(machine_name)
81
+ method_name = machine_name ? "#{machine_name}_next_state" : :next_state
82
+ define_method(method_name) do |event_name|
83
+ next_state_name = self.send(variable_name).next_state_name(event_name)
84
+ self.class.stateful_state_machine(machine_name).find(next_state_name)
70
85
  end
71
86
  end
72
87
 
73
- def define_transitions_method
74
- stateful_variable_name = self.instance_variable_get(:@stateful_variable_name)
75
- define_method(:transitions) do
76
- self.send(stateful_variable_name).transitions
88
+ def define_transitions_method(machine_name: nil)
89
+ variable_name = variable_name_for_machine(machine_name)
90
+ method_name = machine_name ? "#{machine_name}_transitions" : :transitions
91
+ define_method(method_name) do
92
+ self.send(variable_name).transitions
77
93
  end
78
94
  end
79
95
 
80
- def define_initial_stateQ_method
81
- stateful_variable_name = self.instance_variable_get(:@stateful_variable_name)
82
- define_method(:initial_state?) do
83
- self.send(stateful_variable_name) == initial_state
96
+ def define_initial_stateQ_method(machine_name: nil)
97
+ variable_name = variable_name_for_machine(machine_name)
98
+ method_name = machine_name ? "#{machine_name}_initial_state?" : :initial_state?
99
+ define_method(method_name) do
100
+ self.send(variable_name) == self.class.stateful_state_machine(machine_name).initial_state
84
101
  end
85
102
  end
86
103
 
87
- def define_final_stateQ_method
88
- stateful_variable_name = self.instance_variable_get(:@stateful_variable_name)
89
- define_method(:final_state?) do
90
- final_states.include?(self.send(stateful_variable_name))
104
+ def define_final_stateQ_method(machine_name: nil)
105
+ variable_name = variable_name_for_machine(machine_name)
106
+ method_name = machine_name ? "#{machine_name}_final_state?" : :final_state?
107
+ define_method(method_name) do
108
+ self.class.stateful_state_machine(machine_name).final_states.include?(self.send(variable_name))
91
109
  end
92
110
  end
93
-
94
111
  end
95
112
  end
96
113
  end
@@ -1,15 +1,20 @@
1
- # Stateful/States.rb
2
- # Stateful::States
1
+ # Stateful/StateMachine.rb
2
+ # Stateful::StateMachine
3
3
 
4
4
  require_relative 'State'
5
5
 
6
6
  module Stateful
7
- class States
7
+ class StateMachine
8
8
 
9
- attr_reader :all
9
+ attr_accessor :options
10
+ attr_reader(
11
+ :all,
12
+ :machine_name
13
+ )
10
14
 
11
- def initialize(klass, options = {})
15
+ def initialize(klass, machine_name: nil, options: {})
12
16
  @klass = klass
17
+ @machine_name = machine_name
13
18
  @options = options
14
19
  @all = []
15
20
  @initial_state = nil
@@ -65,6 +70,7 @@ module Stateful
65
70
  final_state = State.new(state_name)
66
71
  @final_states << final_state
67
72
  all << final_state
73
+ @klass.define_status_predicate_method(state_name, machine_name: @machine_name)
68
74
  end
69
75
  @final_states
70
76
  else
@@ -77,25 +83,20 @@ module Stateful
77
83
  state = find_or_create(state_name, options)
78
84
  state.instance_eval(&block) if block
79
85
  state.transitions.each do |transition|
80
- @klass.define_event_method(transition)
86
+ @klass.define_event_method(transition, machine_name: @machine_name)
81
87
  end
82
- @klass.define_status_predicate_method(state_name)
88
+ @klass.define_status_predicate_method(state_name, machine_name: @machine_name)
83
89
  state
84
90
  end
85
91
 
86
- def stateful(options = {}, &block)
87
- @options = options
88
- instance_eval(&block) if block
89
- end
90
-
91
92
  private
92
93
 
93
94
  def global_non_deterministic_event_ordering?
95
+ @options ||= {}
94
96
  @options[:global_non_deterministic_event_ordering] ||
95
97
  @options[:non_deterministic_event_ordering] ||
96
98
  @options[:non_deterministic] ||
97
99
  (@options.key?(:deterministic) && !@options[:deterministic])
98
100
  end
99
-
100
101
  end
101
102
  end
@@ -1,5 +1,3 @@
1
1
  module Stateful
2
-
3
- VERSION = '1.0.2'
4
-
2
+ VERSION = '2.0.0'
5
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stateful.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - thoran
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-02-16 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: minitest
@@ -52,7 +52,7 @@ dependencies:
52
52
  - !ruby/object:Gem::Version
53
53
  version: '0'
54
54
  - !ruby/object:Gem::Dependency
55
- name: pg
55
+ name: sqlite3
56
56
  requirement: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - ">="
@@ -79,7 +79,7 @@ files:
79
79
  - lib/Stateful/Poro.rb
80
80
  - lib/Stateful/Poro/ClassMethods.rb
81
81
  - lib/Stateful/State.rb
82
- - lib/Stateful/States.rb
82
+ - lib/Stateful/StateMachine.rb
83
83
  - lib/Stateful/Transition.rb
84
84
  - lib/Stateful/VERSION.rb
85
85
  homepage: http://github.com/thoran/Stateful