stateful_enum 0.5.0 → 0.6.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: fdcc7c193f8597cec775968ecf6cfae38dfe09299d024b877b5da5fae7e5e5ca
4
- data.tar.gz: 20558b138fd9df10e915e40ce6ff197b436a3fe4ce4717f935207dae21d7254e
3
+ metadata.gz: 6d0d82f2cf13496a059030aac0a34a998e47997bcbf6605637fa488c5363454d
4
+ data.tar.gz: 69fc206ccfc3d4290ad0961cac0d011e92ed1fa5421c0064bd881213d52082d5
5
5
  SHA512:
6
- metadata.gz: 1f89d7a82fc8264fbd93b3bd85bb320607409fa662f7726f5b79f04b65da88ee3f080ff39a9ba8d5a2a14c128a1b52fdbf7c773ac6f9cbad8df61cff7052a9e8
7
- data.tar.gz: b2bb43940cffd1be568fff1903920f569585fc3e56a257b9f9d824427ec42de5b2aeaf675faeab48404794ea8179d671dc2a661b98f379e5a7f3f679d6900121
6
+ metadata.gz: e3f5cec3415b7401c36acf28d5dda810d75818cc88b38a768e721757aaf508714ee0613b7926bb0b5e05832df83e6d7deadc3cc0b816eb3e7ab9a6286f6b1399
7
+ data.tar.gz: 6a8d8196552d59c696c42872ae3a9decb62ddef4e75b42566af8e45cd2d3887e3fe6688808ac230f3d35ba7501f4e06328a4fad93462d3e8aee4fca985da4720
@@ -15,6 +15,9 @@ addons:
15
15
 
16
16
  matrix:
17
17
  include:
18
+ - rvm: 2.6.0
19
+ gemfile: gemfiles/Gemfile-rails.6.0.x
20
+
18
21
  - rvm: 2.6.0
19
22
  gemfile: gemfiles/Gemfile-rails.5.2.x
20
23
  - rvm: 2.6.0
data/README.md CHANGED
@@ -122,6 +122,38 @@ end
122
122
 
123
123
  You can define `before` and `after` event hooks inside of an `event` block.
124
124
 
125
+ ### Inspecting All Defined Events And Current Possible Events
126
+
127
+ You can get the list of defined events from the model class:
128
+
129
+ ```ruby
130
+ Bug.stateful_enum.events
131
+ #=> an Array of all defined StatefulEnum::Machine::Event objects
132
+ ```
133
+
134
+ And you can get the list of possible event definitions from the model instance:
135
+
136
+ ```ruby
137
+ Bug.new(status: :assigned).stateful_enum.possible_events
138
+ #=> an Array of StatefulEnum::Machine::Event objects that are callable from the receiver object
139
+ ```
140
+
141
+ Maybe what you really need for your app is the list of possible event "names":
142
+
143
+ ```ruby
144
+ Bug.new(status: :assigned).stateful_enum.possible_event_names
145
+ #=> [:resolve, :close]
146
+ ```
147
+
148
+ You can get the list of next possible state names as well:
149
+
150
+ ```ruby
151
+ Bug.new(status: :assigned).stateful_enum.possible_states
152
+ #=> [:resolved, :closed]
153
+ ```
154
+
155
+ These features would help some kind of metaprogramming over state transitions.
156
+
125
157
 
126
158
  ## Generating State Machine Diagrams
127
159
 
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec path: '..'
4
+
5
+ gem 'rails', '~> 6.0.0.rc1'
6
+ gem 'selenium-webdriver'
@@ -65,7 +65,6 @@ module StatefulEnum
65
65
  end
66
66
  end
67
67
 
68
- class Item < Struct.new(:from, :to, :label)
69
- end
68
+ Item = Struct.new(:from, :to, :label)
70
69
  end
71
70
  end
@@ -10,13 +10,13 @@ module StatefulEnum
10
10
  # end
11
11
  # end
12
12
  def enum(definitions, &block)
13
- prefix, suffix = definitions[:_prefix], definitions[:_suffix] if Rails::VERSION::STRING >= '5'
13
+ prefix, suffix = definitions[:_prefix], definitions[:_suffix] if Rails::VERSION::MAJOR >= 5
14
14
  enum = super definitions
15
15
 
16
16
  if block
17
17
  definitions.each_key do |column|
18
18
  states = enum[column]
19
- StatefulEnum::Machine.new self, column, (states.is_a?(Hash) ? states.keys : states), prefix, suffix, &block
19
+ (@_defined_stateful_enums ||= []) << StatefulEnum::Machine.new(self, column, (states.is_a?(Hash) ? states.keys : states), prefix, suffix, &block)
20
20
  end
21
21
  end
22
22
  end
@@ -2,8 +2,10 @@
2
2
 
3
3
  module StatefulEnum
4
4
  class Machine
5
+ attr_reader :events
6
+
5
7
  def initialize(model, column, states, prefix, suffix, &block)
6
- @model, @column, @states, @event_names = model, column, states, []
8
+ @model, @column, @states, @events = model, column, states, []
7
9
  @prefix = if prefix
8
10
  prefix == true ? "#{column}_" : "#{prefix}_"
9
11
  end
@@ -20,40 +22,41 @@ module StatefulEnum
20
22
  end
21
23
 
22
24
  def event(name, &block)
23
- raise ArgumentError, "event: :#{name} has already been defined." if @event_names.include? name
24
- Event.new @model, @column, @states, @prefix, @suffix, name, &block
25
- @event_names << name
25
+ raise ArgumentError, "event: :#{name} has already been defined." if @events.map(&:name).include? name
26
+ @events << Event.new(@model, @column, @states, @prefix, @suffix, name, &block)
26
27
  end
27
28
 
28
29
  class Event
30
+ attr_reader :name, :value_method_name
31
+
29
32
  def initialize(model, column, states, prefix, suffix, name, &block)
30
33
  @states, @name, @transitions, @before, @after = states, name, {}, [], []
31
34
 
32
35
  instance_eval(&block) if block
33
36
 
34
37
  transitions, before, after = @transitions, @before, @after
35
- new_method_name = "#{prefix}#{name}#{suffix}"
38
+ @value_method_name = value_method_name = :"#{prefix}#{name}#{suffix}"
36
39
 
37
40
  # defining event methods
38
41
  model.class_eval do
39
42
  # def assign()
40
- detect_enum_conflict! column, new_method_name
43
+ detect_enum_conflict! column, value_method_name
41
44
 
42
45
  # defining callbacks
43
- define_callbacks new_method_name
46
+ define_callbacks value_method_name
44
47
  before.each do |before_callback|
45
- model.set_callback new_method_name, :before, before_callback
48
+ model.set_callback value_method_name, :before, before_callback
46
49
  end
47
50
  after.each do |after_callback|
48
- model.set_callback new_method_name, :after, after_callback
51
+ model.set_callback value_method_name, :after, after_callback
49
52
  end
50
53
 
51
- define_method new_method_name do
54
+ define_method value_method_name do
52
55
  to, condition = transitions[send(column).to_sym]
53
56
  #TODO better error
54
57
  if to && (!condition || instance_exec(&condition))
55
58
  #TODO transaction?
56
- run_callbacks new_method_name do
59
+ run_callbacks value_method_name do
57
60
  original_method = self.class.send(:_enum_methods_module).instance_method "#{prefix}#{to}#{suffix}!"
58
61
  original_method.bind(self).call
59
62
  end
@@ -63,14 +66,14 @@ module StatefulEnum
63
66
  end
64
67
 
65
68
  # def assign!()
66
- detect_enum_conflict! column, "#{new_method_name}!"
67
- define_method "#{new_method_name}!" do
68
- send(new_method_name) || raise('Invalid transition')
69
+ detect_enum_conflict! column, "#{value_method_name}!"
70
+ define_method "#{value_method_name}!" do
71
+ send(value_method_name) || raise('Invalid transition')
69
72
  end
70
73
 
71
74
  # def can_assign?()
72
- detect_enum_conflict! column, "can_#{new_method_name}?"
73
- define_method "can_#{new_method_name}?" do
75
+ detect_enum_conflict! column, "can_#{value_method_name}?"
76
+ define_method "can_#{value_method_name}?" do
74
77
  state = send(column).to_sym
75
78
  return false unless transitions.key? state
76
79
  _to, condition = transitions[state]
@@ -78,8 +81,8 @@ module StatefulEnum
78
81
  end
79
82
 
80
83
  # def assign_transition()
81
- detect_enum_conflict! column, "#{new_method_name}_transition"
82
- define_method "#{new_method_name}_transition" do
84
+ detect_enum_conflict! column, "#{value_method_name}_transition"
85
+ define_method "#{value_method_name}_transition" do
83
86
  transitions[send(column).to_sym].try! :first
84
87
  end
85
88
  end
@@ -1,11 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'stateful_enum/active_record_extension'
4
+ require 'stateful_enum/state_inspection'
4
5
 
5
6
  module StatefulEnum
6
7
  class Railtie < ::Rails::Railtie
7
- ActiveSupport.on_load :active_record do
8
- ::ActiveRecord::Base.extend StatefulEnum::ActiveRecordEnumExtension
8
+ initializer 'stateful_enum' do
9
+ ActiveSupport.on_load :active_record do
10
+ ::ActiveRecord::Base.extend StatefulEnum::ActiveRecordEnumExtension
11
+ ::ActiveRecord::Base.include StatefulEnum::StateInspection
12
+ end
9
13
  end
10
14
  end
11
15
  end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stateful_enum/machine'
4
+
5
+ module StatefulEnum
6
+ module StateInspection
7
+ extend ActiveSupport::Concern
8
+
9
+ module ClassMethods
10
+ def stateful_enum
11
+ @_defined_stateful_enums
12
+ end
13
+ end
14
+
15
+ def stateful_enum
16
+ StateInspector.new(self.class.stateful_enum, self)
17
+ end
18
+ end
19
+
20
+ class StateInspector
21
+ def initialize(defined_stateful_enums, model_instance)
22
+ @defined_stateful_enums, @model_instance = defined_stateful_enums, model_instance
23
+ end
24
+
25
+ # List of possible events from the current state
26
+ def possible_events
27
+ @defined_stateful_enums.flat_map {|se| se.events.select {|e| @model_instance.send("can_#{e.value_method_name}?") } }
28
+ end
29
+
30
+ # List of possible event names from the current state
31
+ def possible_event_names
32
+ possible_events.map(&:value_method_name)
33
+ end
34
+
35
+ # List of transitionable states from the current state
36
+ def possible_states
37
+ @defined_stateful_enums.flat_map do |stateful_enum|
38
+ col = stateful_enum.instance_variable_get :@column
39
+ pe = stateful_enum.events.select {|e| @model_instance.send("can_#{e.value_method_name}?") }
40
+ pe.flat_map {|e| e.instance_variable_get(:@transitions)[@model_instance.send(col).to_sym].first }
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module StatefulEnum
4
- VERSION = '0.5.0'
4
+ VERSION = '0.6.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stateful_enum
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Akira Matsuda
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-02-07 00:00:00.000000000 Z
11
+ date: 2019-06-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -114,6 +114,7 @@ files:
114
114
  - gemfiles/Gemfile-rails.5.0.x
115
115
  - gemfiles/Gemfile-rails.5.1.x
116
116
  - gemfiles/Gemfile-rails.5.2.x
117
+ - gemfiles/Gemfile-rails.6.0.x
117
118
  - gemfiles/Gemfile-rails.edge
118
119
  - lib/generators/stateful_enum/graph_generator.rb
119
120
  - lib/generators/stateful_enum/plantuml_generator.rb
@@ -121,6 +122,7 @@ files:
121
122
  - lib/stateful_enum/active_record_extension.rb
122
123
  - lib/stateful_enum/machine.rb
123
124
  - lib/stateful_enum/railtie.rb
125
+ - lib/stateful_enum/state_inspection.rb
124
126
  - lib/stateful_enum/version.rb
125
127
  - stateful_enum.gemspec
126
128
  homepage: https://github.com/amatsuda/stateful_enum
@@ -142,8 +144,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
142
144
  - !ruby/object:Gem::Version
143
145
  version: '0'
144
146
  requirements: []
145
- rubyforge_project:
146
- rubygems_version: 2.7.8
147
+ rubygems_version: 3.0.3
147
148
  signing_key:
148
149
  specification_version: 4
149
150
  summary: A state machine plugin on top of ActiveRecord::Enum