ultra-smart-sys 0.0.1

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.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/state_machines-0.201.0/LICENSE.txt +23 -0
  3. data/state_machines-0.201.0/README.md +1024 -0
  4. data/state_machines-0.201.0/lib/state_machines/async_mode/async_event_extensions.rb +49 -0
  5. data/state_machines-0.201.0/lib/state_machines/async_mode/async_events.rb +282 -0
  6. data/state_machines-0.201.0/lib/state_machines/async_mode/async_machine.rb +60 -0
  7. data/state_machines-0.201.0/lib/state_machines/async_mode/async_transition_collection.rb +136 -0
  8. data/state_machines-0.201.0/lib/state_machines/async_mode/thread_safe_state.rb +47 -0
  9. data/state_machines-0.201.0/lib/state_machines/async_mode.rb +64 -0
  10. data/state_machines-0.201.0/lib/state_machines/branch.rb +246 -0
  11. data/state_machines-0.201.0/lib/state_machines/callback.rb +223 -0
  12. data/state_machines-0.201.0/lib/state_machines/core.rb +43 -0
  13. data/state_machines-0.201.0/lib/state_machines/core_ext/class/state_machine.rb +5 -0
  14. data/state_machines-0.201.0/lib/state_machines/core_ext.rb +4 -0
  15. data/state_machines-0.201.0/lib/state_machines/error.rb +115 -0
  16. data/state_machines-0.201.0/lib/state_machines/eval_helpers.rb +227 -0
  17. data/state_machines-0.201.0/lib/state_machines/event.rb +247 -0
  18. data/state_machines-0.201.0/lib/state_machines/event_collection.rb +149 -0
  19. data/state_machines-0.201.0/lib/state_machines/extensions.rb +150 -0
  20. data/state_machines-0.201.0/lib/state_machines/helper_module.rb +19 -0
  21. data/state_machines-0.201.0/lib/state_machines/integrations/base.rb +49 -0
  22. data/state_machines-0.201.0/lib/state_machines/integrations.rb +111 -0
  23. data/state_machines-0.201.0/lib/state_machines/machine/action_hooks.rb +53 -0
  24. data/state_machines-0.201.0/lib/state_machines/machine/async_extensions.rb +88 -0
  25. data/state_machines-0.201.0/lib/state_machines/machine/callbacks.rb +333 -0
  26. data/state_machines-0.201.0/lib/state_machines/machine/class_methods.rb +95 -0
  27. data/state_machines-0.201.0/lib/state_machines/machine/configuration.rb +128 -0
  28. data/state_machines-0.201.0/lib/state_machines/machine/event_methods.rb +436 -0
  29. data/state_machines-0.201.0/lib/state_machines/machine/helper_generators.rb +125 -0
  30. data/state_machines-0.201.0/lib/state_machines/machine/integration.rb +92 -0
  31. data/state_machines-0.201.0/lib/state_machines/machine/parsing.rb +77 -0
  32. data/state_machines-0.201.0/lib/state_machines/machine/rendering.rb +17 -0
  33. data/state_machines-0.201.0/lib/state_machines/machine/scoping.rb +44 -0
  34. data/state_machines-0.201.0/lib/state_machines/machine/state_methods.rb +398 -0
  35. data/state_machines-0.201.0/lib/state_machines/machine/utilities.rb +86 -0
  36. data/state_machines-0.201.0/lib/state_machines/machine/validation.rb +39 -0
  37. data/state_machines-0.201.0/lib/state_machines/machine.rb +615 -0
  38. data/state_machines-0.201.0/lib/state_machines/machine_collection.rb +105 -0
  39. data/state_machines-0.201.0/lib/state_machines/macro_methods.rb +522 -0
  40. data/state_machines-0.201.0/lib/state_machines/matcher.rb +124 -0
  41. data/state_machines-0.201.0/lib/state_machines/matcher_helpers.rb +56 -0
  42. data/state_machines-0.201.0/lib/state_machines/node_collection.rb +226 -0
  43. data/state_machines-0.201.0/lib/state_machines/options_validator.rb +72 -0
  44. data/state_machines-0.201.0/lib/state_machines/path.rb +123 -0
  45. data/state_machines-0.201.0/lib/state_machines/path_collection.rb +91 -0
  46. data/state_machines-0.201.0/lib/state_machines/state.rb +314 -0
  47. data/state_machines-0.201.0/lib/state_machines/state_collection.rb +113 -0
  48. data/state_machines-0.201.0/lib/state_machines/state_context.rb +134 -0
  49. data/state_machines-0.201.0/lib/state_machines/stdio_renderer.rb +74 -0
  50. data/state_machines-0.201.0/lib/state_machines/syntax_validator.rb +54 -0
  51. data/state_machines-0.201.0/lib/state_machines/test_helper.rb +775 -0
  52. data/state_machines-0.201.0/lib/state_machines/transition.rb +593 -0
  53. data/state_machines-0.201.0/lib/state_machines/transition_collection.rb +310 -0
  54. data/state_machines-0.201.0/lib/state_machines/version.rb +5 -0
  55. data/state_machines-0.201.0/lib/state_machines.rb +6 -0
  56. data/ultra-smart-sys.gemspec +12 -0
  57. metadata +96 -0
@@ -0,0 +1,150 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StateMachines
4
+ module ClassMethods
5
+ def self.extended(base) # :nodoc:
6
+ base.class_eval do
7
+ @state_machines = MachineCollection.new
8
+ end
9
+ end
10
+
11
+ # Gets the current list of state machines defined for this class. This
12
+ # class-level attribute acts like an inheritable attribute. The attribute
13
+ # is available to each subclass, each having a copy of its superclass's
14
+ # attribute.
15
+ #
16
+ # The hash of state machines maps <tt>:attribute</tt> => +machine+, e.g.
17
+ #
18
+ # Vehicle.state_machines # => {:state => #<StateMachines::Machine:0xb6f6e4a4 ...>}
19
+ def state_machines
20
+ @state_machines ||= superclass.state_machines.dup
21
+ end
22
+ end
23
+
24
+ module InstanceMethods
25
+ # Runs one or more events in parallel. All events will run through the
26
+ # following steps:
27
+ # * Before callbacks
28
+ # * Persist state
29
+ # * Invoke action
30
+ # * After callbacks
31
+ #
32
+ # For example, if two events (for state machines A and B) are run in
33
+ # parallel, the order in which steps are run is:
34
+ # * A - Before transition callbacks
35
+ # * B - Before transition callbacks
36
+ # * A - Persist new state
37
+ # * B - Persist new state
38
+ # * A - Invoke action
39
+ # * B - Invoke action (only if different than A's action)
40
+ # * A - After transition callbacks
41
+ # * B - After transition callbacks
42
+ #
43
+ # *Note* that multiple events on the same state machine / attribute cannot
44
+ # be run in parallel. If this is attempted, an ArgumentError will be
45
+ # raised.
46
+ #
47
+ # == Halting callbacks
48
+ #
49
+ # When running multiple events in parallel, special consideration should
50
+ # be taken with regard to how halting within callbacks affects the flow.
51
+ #
52
+ # For *before* callbacks, any <tt>:halt</tt> error that's thrown will
53
+ # immediately cancel the perform for all transitions. As a result, it's
54
+ # possible for one event's transition to affect the continuation of
55
+ # another.
56
+ #
57
+ # On the other hand, any <tt>:halt</tt> error that's thrown within an
58
+ # *after* callback with only affect that event's transition. Other
59
+ # transitions will continue to run their own callbacks.
60
+ #
61
+ # == Example
62
+ #
63
+ # class Vehicle
64
+ # state_machine :initial => :parked do
65
+ # event :ignite do
66
+ # transition :parked => :idling
67
+ # end
68
+ #
69
+ # event :park do
70
+ # transition :idling => :parked
71
+ # end
72
+ # end
73
+ #
74
+ # state_machine :alarm_state, :namespace => 'alarm', :initial => :on do
75
+ # event :enable do
76
+ # transition all => :active
77
+ # end
78
+ #
79
+ # event :disable do
80
+ # transition all => :off
81
+ # end
82
+ # end
83
+ # end
84
+ #
85
+ # vehicle = Vehicle.new # => #<Vehicle:0xb7c02850 @state="parked", @alarm_state="active">
86
+ # vehicle.state # => "parked"
87
+ # vehicle.alarm_state # => "active"
88
+ #
89
+ # vehicle.fire_events(:ignite, :disable_alarm) # => true
90
+ # vehicle.state # => "idling"
91
+ # vehicle.alarm_state # => "off"
92
+ #
93
+ # # If any event fails, the entire event chain fails
94
+ # vehicle.fire_events(:ignite, :enable_alarm) # => false
95
+ # vehicle.state # => "idling"
96
+ # vehicle.alarm_state # => "off"
97
+ #
98
+ # # Exception raised on invalid event
99
+ # vehicle.fire_events(:park, :invalid) # => StateMachines::InvalidEvent: :invalid is an unknown event
100
+ # vehicle.state # => "idling"
101
+ # vehicle.alarm_state # => "off"
102
+ def fire_events(*events)
103
+ self.class.state_machines.fire_events(self, *events)
104
+ end
105
+
106
+ # Run one or more events in parallel. If any event fails to run, then
107
+ # a StateMachines::InvalidTransition exception will be raised.
108
+ #
109
+ # See StateMachines::InstanceMethods#fire_events for more information.
110
+ #
111
+ # == Example
112
+ #
113
+ # class Vehicle
114
+ # state_machine :initial => :parked do
115
+ # event :ignite do
116
+ # transition :parked => :idling
117
+ # end
118
+ #
119
+ # event :park do
120
+ # transition :idling => :parked
121
+ # end
122
+ # end
123
+ #
124
+ # state_machine :alarm_state, :namespace => 'alarm', :initial => :active do
125
+ # event :enable do
126
+ # transition all => :active
127
+ # end
128
+ #
129
+ # event :disable do
130
+ # transition all => :off
131
+ # end
132
+ # end
133
+ # end
134
+ #
135
+ # vehicle = Vehicle.new # => #<Vehicle:0xb7c02850 @state="parked", @alarm_state="active">
136
+ # vehicle.fire_events(:ignite, :disable_alarm) # => true
137
+ #
138
+ # vehicle.fire_events!(:ignite, :disable_alarm) # => StateMachines::InvalidParallelTransition: Cannot run events in parallel: ignite, disable_alarm
139
+ def fire_events!(*events)
140
+ run_action = [true, false].include?(events.last) ? events.pop : true
141
+ fire_events(*(events + [run_action])) || raise(StateMachines::InvalidParallelTransition.new(self, events))
142
+ end
143
+
144
+ protected
145
+
146
+ def initialize_state_machines(options = {}, &) # :nodoc:
147
+ self.class.state_machines.initialize_states(self, options, &)
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StateMachines
4
+ # Represents a type of module that defines instance / class methods for a
5
+ # state machine
6
+ class HelperModule < Module # :nodoc:
7
+ def initialize(machine, kind)
8
+ @machine = machine
9
+ @kind = kind
10
+ end
11
+
12
+ # Provides a human-readable description of the module
13
+ def to_s
14
+ owner_class = @machine.owner_class
15
+ owner_class_name = owner_class.name && !owner_class.name.empty? ? owner_class.name : owner_class.to_s
16
+ "#{owner_class_name} #{@machine.name.inspect} #{@kind} helpers"
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StateMachines
4
+ module Integrations
5
+ # Provides a set of base helpers for managing individual integrations
6
+ module Base
7
+ module ClassMethods
8
+ # The default options to use for state machines using this integration
9
+ attr_reader :defaults
10
+
11
+ # The name of the integration
12
+ def integration_name
13
+ @integration_name ||= begin
14
+ name = self.name.split('::').last
15
+ name.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
16
+ name.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
17
+ name.downcase!
18
+ name.to_sym
19
+ end
20
+ end
21
+
22
+ # The list of ancestor names that cause this integration to matched.
23
+ def matching_ancestors
24
+ []
25
+ end
26
+
27
+ # Whether the integration should be used for the given class.
28
+ def matches?(klass)
29
+ matching_ancestors.any? { |ancestor| klass <= ancestor }
30
+ end
31
+
32
+ # Whether the integration should be used for the given list of ancestors.
33
+ def matches_ancestors?(ancestors)
34
+ (ancestors & matching_ancestors).any?
35
+ end
36
+
37
+ # Additional options that this integration adds to the state machine.
38
+ # Integrations can override this method to specify additional valid options.
39
+ def integration_options
40
+ []
41
+ end
42
+ end
43
+
44
+ def self.included(base) # :nodoc:
45
+ base.extend ClassMethods
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StateMachines
4
+ # Integrations allow state machines to take advantage of features within the
5
+ # context of a particular library. This is currently most useful with
6
+ # database libraries. For example, the various database integrations allow
7
+ # state machines to hook into features like:
8
+ # * Saving
9
+ # * Transactions
10
+ # * Observers
11
+ # * Scopes
12
+ # * Callbacks
13
+ # * Validation errors
14
+ #
15
+ # This type of integration allows the user to work with state machines in a
16
+ # fashion similar to other object models in their application.
17
+ #
18
+ # The integration interface is loosely defined by various unimplemented
19
+ # methods in the StateMachines::Machine class. See that class or the various
20
+ # built-in integrations for more information about how to define additional
21
+ # integrations.
22
+ module Integrations
23
+ @integrations = []
24
+
25
+ class << self
26
+ # Register integration
27
+ def register(name_or_module)
28
+ case name_or_module.class.to_s
29
+ when 'Module'
30
+ add(name_or_module)
31
+ else
32
+ raise IntegrationError
33
+ end
34
+ true
35
+ end
36
+
37
+ def reset # :nodoc:#
38
+ @integrations = []
39
+ end
40
+
41
+ # Gets a list of all of the available integrations for use.
42
+ #
43
+ # == Example
44
+ #
45
+ # StateMachines::Integrations.integrations
46
+ # # => []
47
+ # StateMachines::Integrations.register(StateMachines::Integrations::ActiveModel)
48
+ # StateMachines::Integrations.integrations
49
+ # # => [StateMachines::Integrations::ActiveModel]
50
+ attr_reader :integrations
51
+
52
+ alias list integrations
53
+
54
+ # Attempts to find an integration that matches the given class. This will
55
+ # look through all of the built-in integrations under the StateMachines::Integrations
56
+ # namespace and find one that successfully matches the class.
57
+ #
58
+ # == Examples
59
+ #
60
+ # class Vehicle
61
+ # end
62
+ #
63
+ # class ActiveModelVehicle
64
+ # include ActiveModel::Observing
65
+ # include ActiveModel::Validations
66
+ # end
67
+ #
68
+ # class ActiveRecordVehicle < ActiveRecord::Base
69
+ # end
70
+ #
71
+ # StateMachines::Integrations.match(Vehicle) # => nil
72
+ # StateMachines::Integrations.match(ActiveModelVehicle) # => StateMachines::Integrations::ActiveModel
73
+ # StateMachines::Integrations.match(ActiveRecordVehicle) # => StateMachines::Integrations::ActiveRecord
74
+ def match(klass)
75
+ integrations.detect { |integration| integration.matches?(klass) }
76
+ end
77
+
78
+ # Attempts to find an integration that matches the given list of ancestors.
79
+ # This will look through all of the built-in integrations under the StateMachines::Integrations
80
+ # namespace and find one that successfully matches one of the ancestors.
81
+ #
82
+ # == Examples
83
+ #
84
+ # StateMachines::Integrations.match_ancestors([]) # => nil
85
+ # StateMachines::Integrations.match_ancestors([ActiveRecord::Base]) # => StateMachines::Integrations::ActiveModel
86
+ def match_ancestors(ancestors)
87
+ integrations.detect { |integration| integration.matches_ancestors?(ancestors) }
88
+ end
89
+
90
+ # Finds an integration with the given name. If the integration cannot be
91
+ # found, then a NameError exception will be raised.
92
+ #
93
+ # == Examples
94
+ #
95
+ # StateMachines::Integrations.find_by_name(:active_model) # => StateMachines::Integrations::ActiveModel
96
+ # StateMachines::Integrations.find_by_name(:active_record) # => StateMachines::Integrations::ActiveRecord
97
+ # StateMachines::Integrations.find_by_name(:invalid) # => StateMachines::IntegrationNotFound: :invalid is an invalid integration
98
+ def find_by_name(name)
99
+ integrations.detect { |integration| integration.integration_name == name } || raise(IntegrationNotFound.new(name))
100
+ end
101
+
102
+ private
103
+
104
+ def add(integration)
105
+ return unless integration.respond_to?(:integration_name)
106
+
107
+ @integrations.insert(0, integration) unless @integrations.include?(integration)
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StateMachines
4
+ class Machine
5
+ module ActionHooks
6
+ protected
7
+
8
+ # Determines whether action helpers should be defined for this machine.
9
+ # This is only true if there is an action configured and no other machines
10
+ # have process this same configuration already.
11
+ def define_action_helpers?
12
+ action && owner_class.state_machines.none? { |_name, machine| machine.action == action && machine != self }
13
+ end
14
+
15
+ # Adds helper methods for automatically firing events when an action
16
+ # is invoked
17
+ def define_action_helpers
18
+ return unless action_hook
19
+
20
+ @action_hook_defined = true
21
+ define_action_hook
22
+ end
23
+
24
+ # Hooks directly into actions by defining the same method in an included
25
+ # module. As a result, when the action gets invoked, any state events
26
+ # defined for the object will get run. Method visibility is preserved.
27
+ def define_action_hook
28
+ action_hook = self.action_hook
29
+ action = self.action
30
+ private_action_hook = owner_class.private_method_defined?(action_hook)
31
+
32
+ # Only define helper if it hasn't
33
+ define_helper :instance, <<-END_EVAL, __FILE__, __LINE__ + 1
34
+ def #{action_hook}(*)
35
+ self.class.state_machines.transitions(self, #{action.inspect}).perform { super }
36
+ end
37
+
38
+ private #{action_hook.inspect} if #{private_action_hook}
39
+ END_EVAL
40
+ end
41
+
42
+ # The method to hook into for triggering transitions when invoked. By
43
+ # default, this is the action configured for the machine.
44
+ #
45
+ # Since the default hook technique relies on module inheritance, the
46
+ # action must be defined in an ancestor of the owner classs in order for
47
+ # it to be the action hook.
48
+ def action_hook
49
+ action && owner_class_ancestor_has_method?(:instance, action) ? action : nil
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file provides optional async extensions for the Machine class.
4
+ # It should only be loaded when async functionality is explicitly requested.
5
+
6
+ module StateMachines
7
+ class Machine
8
+ # AsyncMode extensions for the Machine class
9
+ # Provides async-aware methods while maintaining backward compatibility
10
+ module AsyncExtensions
11
+ # Instance methods added to Machine for async support
12
+
13
+ # Configure this specific machine instance for async mode
14
+ #
15
+ # Example:
16
+ # class Vehicle
17
+ # state_machine initial: :parked do
18
+ # configure_async_mode! # Enable async for this machine
19
+ #
20
+ # event :ignite do
21
+ # transition parked: :idling
22
+ # end
23
+ # end
24
+ # end
25
+ def configure_async_mode!(enabled = true)
26
+ if enabled
27
+ begin
28
+ require 'state_machines/async_mode'
29
+ @async_mode_enabled = true
30
+
31
+ owner_class.include(StateMachines::AsyncMode::ThreadSafeState)
32
+ owner_class.include(StateMachines::AsyncMode::AsyncEvents)
33
+ extend(StateMachines::AsyncMode::AsyncMachine)
34
+
35
+ # Extend events to generate async versions
36
+ events.each do |event|
37
+ event.extend(StateMachines::AsyncMode::AsyncEventExtensions)
38
+ end
39
+ rescue LoadError => e
40
+ # Fallback to sync mode with warning (only once per class)
41
+ unless owner_class.instance_variable_get(:@async_fallback_warned)
42
+ warn <<~WARNING
43
+ ⚠️ #{owner_class.name}: Async mode requested but not available on #{RUBY_ENGINE}.
44
+
45
+ #{e.message}
46
+
47
+ ⚠️ Falling back to synchronous mode. Results may be unpredictable due to engine limitations.
48
+ For production async support, use MRI Ruby (CRuby) 3.2+
49
+ WARNING
50
+ owner_class.instance_variable_set(:@async_fallback_warned, true)
51
+ end
52
+
53
+ @async_mode_enabled = false
54
+ end
55
+ else
56
+ @async_mode_enabled = false
57
+ end
58
+
59
+ self
60
+ end
61
+
62
+ # Check if this specific machine instance has async mode enabled
63
+ def async_mode_enabled?
64
+ @async_mode_enabled || false
65
+ end
66
+
67
+ # Thread-safe version of state reading
68
+ def read_safely(object, attribute, ivar = false)
69
+ object.read_state_safely(self, attribute, ivar)
70
+ end
71
+
72
+ # Thread-safe version of state writing
73
+ def write_safely(object, attribute, value, ivar = false)
74
+ object.write_state_safely(self, attribute, value, ivar)
75
+ end
76
+
77
+ # Thread-safe callback execution for async operations
78
+ def run_callbacks_safely(type, object, context, transition)
79
+ object.state_machine_mutex.with_write_lock do
80
+ callbacks[type].each { |callback| callback.call(object, context, transition) }
81
+ end
82
+ end
83
+ end
84
+
85
+ # Include async extensions by default (but only load AsyncMode when requested)
86
+ include AsyncExtensions
87
+ end
88
+ end