state_machines-activerecord 0.8.0 → 0.200.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 +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +178 -8
- data/lib/state_machines/integrations/active_record/locale.rb +12 -9
- data/lib/state_machines/integrations/active_record/type/integer.rb +122 -0
- data/lib/state_machines/integrations/active_record/version.rb +3 -1
- data/lib/state_machines/integrations/active_record.rb +548 -181
- data/lib/state_machines-activerecord.rb +2 -0
- metadata +37 -154
- data/.gitignore +0 -22
- data/.travis.yml +0 -19
- data/Appraisals +0 -34
- data/Gemfile +0 -6
- data/Rakefile +0 -9
- data/gemfiles/active_record_5.1.gemfile +0 -14
- data/gemfiles/active_record_5.2.gemfile +0 -14
- data/gemfiles/active_record_6.0.gemfile +0 -14
- data/gemfiles/active_record_6.1.gemfile +0 -14
- data/gemfiles/active_record_edge.gemfile +0 -14
- data/log/.gitkeep +0 -0
- data/state_machines-activerecord.gemspec +0 -28
- data/test/files/en.yml +0 -5
- data/test/files/models/post.rb +0 -11
- data/test/integration_test.rb +0 -25
- data/test/machine_by_default_test.rb +0 -16
- data/test/machine_errors_test.rb +0 -19
- data/test/machine_multiple_test.rb +0 -17
- data/test/machine_nested_action_test.rb +0 -38
- data/test/machine_unmigrated_test.rb +0 -14
- data/test/machine_with_aliased_attribute_test.rb +0 -23
- data/test/machine_with_callbacks_test.rb +0 -172
- data/test/machine_with_column_state_attribute_test.rb +0 -44
- data/test/machine_with_complex_pluralization_scopes_test.rb +0 -16
- data/test/machine_with_conflicting_predicate_test.rb +0 -18
- data/test/machine_with_conflicting_state_name_test.rb +0 -29
- data/test/machine_with_custom_attribute_test.rb +0 -21
- data/test/machine_with_default_scope_test.rb +0 -18
- data/test/machine_with_different_column_default_test.rb +0 -27
- data/test/machine_with_different_integer_column_default_test.rb +0 -29
- data/test/machine_with_dirty_attribute_and_custom_attributes_during_loopback_test.rb +0 -24
- data/test/machine_with_dirty_attribute_and_state_events_test.rb +0 -20
- data/test/machine_with_dirty_attributes_and_custom_attribute_test.rb +0 -32
- data/test/machine_with_dirty_attributes_during_loopback_test.rb +0 -22
- data/test/machine_with_dirty_attributes_test.rb +0 -35
- data/test/machine_with_dynamic_initial_state_test.rb +0 -99
- data/test/machine_with_event_attributes_on_autosave_test.rb +0 -48
- data/test/machine_with_event_attributes_on_custom_action_test.rb +0 -41
- data/test/machine_with_event_attributes_on_save_bang_test.rb +0 -82
- data/test/machine_with_event_attributes_on_save_test.rb +0 -244
- data/test/machine_with_event_attributes_on_validation_test.rb +0 -143
- data/test/machine_with_events_test.rb +0 -13
- data/test/machine_with_failed_action_test.rb +0 -40
- data/test/machine_with_failed_after_callbacks_test.rb +0 -35
- data/test/machine_with_failed_before_callbacks_test.rb +0 -36
- data/test/machine_with_initialized_state_test.rb +0 -41
- data/test/machine_with_internationalization_test.rb +0 -180
- data/test/machine_with_loopback_test.rb +0 -22
- data/test/machine_with_non_column_state_attribute_defined_test.rb +0 -29
- data/test/machine_with_same_column_default_test.rb +0 -26
- data/test/machine_with_same_integer_column_default_test.rb +0 -30
- data/test/machine_with_scopes_and_joins_test.rb +0 -37
- data/test/machine_with_scopes_and_owner_subclass_test.rb +0 -27
- data/test/machine_with_scopes_test.rb +0 -70
- data/test/machine_with_state_driven_validations_test.rb +0 -30
- data/test/machine_with_states_test.rb +0 -13
- data/test/machine_with_static_initial_state_test.rb +0 -166
- data/test/machine_with_transactions_test.rb +0 -26
- data/test/machine_with_validations_and_custom_attribute_test.rb +0 -21
- data/test/machine_with_validations_test.rb +0 -47
- data/test/machine_without_database_test.rb +0 -20
- data/test/machine_without_transactions_test.rb +0 -26
- data/test/model_test.rb +0 -12
- data/test/test_helper.rb +0 -52
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f022e63c2bfd6af186733c95cbfc19cb7f25dfff128c791e5199b1a3f4e6d760
|
|
4
|
+
data.tar.gz: '094b3a2befdd974fa1828e9237f75f0a5a38319b7e38b56b8a3dda376a1e797d'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cfb9f8bca11c37eeaff38ff0a237c2cc241986bba88ee4a8859199ea05ee7d06b4449da73574e0125f678de3082f3ba4e472f491f0efe9100fc2b585cac5e818
|
|
7
|
+
data.tar.gz: 8fb449a5ead40d4cf43e92208d307bb34f557e9aae068cda123c968ded28aecfa7a97c416426b04f99afd2550a50b54f852bc6e04c5ab6dc4fef62199d5e615d
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
[](https://codeclimate.com/github/state-machines/state_machines-activerecord)
|
|
1
|
+
[](https://github.com/state-machines/state_machines-activerecord/actions/workflows/ruby.yml)
|
|
3
2
|
|
|
4
3
|
# StateMachines Active Record Integration
|
|
5
4
|
|
|
6
|
-
The Active Record
|
|
5
|
+
The Active Record 7.2+ integration adds support for database transactions, automatically
|
|
7
6
|
saving the record, named scopes, validation errors.
|
|
8
7
|
|
|
8
|
+
## Requirements
|
|
9
|
+
|
|
10
|
+
- Ruby 3.2+
|
|
11
|
+
- Rails 7.2+
|
|
12
|
+
|
|
9
13
|
## Installation
|
|
10
14
|
|
|
11
15
|
Add this line to your application's Gemfile:
|
|
@@ -27,7 +31,7 @@ For the complete usage guide, see http://www.rubydoc.info/github/state-machines/
|
|
|
27
31
|
### Example
|
|
28
32
|
|
|
29
33
|
```ruby
|
|
30
|
-
class Vehicle <
|
|
34
|
+
class Vehicle < ApplicationRecord
|
|
31
35
|
state_machine :initial => :parked do
|
|
32
36
|
before_transition :parked => any - :parked, :do => :put_on_seatbelt
|
|
33
37
|
after_transition any => :parked do |vehicle, transition|
|
|
@@ -40,7 +44,7 @@ class Vehicle < ActiveRecord::Base
|
|
|
40
44
|
end
|
|
41
45
|
|
|
42
46
|
state :first_gear, :second_gear do
|
|
43
|
-
|
|
47
|
+
validates :seatbelt_on, presence: true
|
|
44
48
|
end
|
|
45
49
|
end
|
|
46
50
|
|
|
@@ -64,7 +68,173 @@ Vehicle.with_state(:parked) # also plural #with_states
|
|
|
64
68
|
Vehicle.without_states(:first_gear, :second_gear) # also singular #without_state
|
|
65
69
|
```
|
|
66
70
|
|
|
67
|
-
|
|
71
|
+
#### Transparent Scopes
|
|
72
|
+
State scopes will return all records when `nil` is passed, making them perfect for search filters:
|
|
73
|
+
|
|
74
|
+
```ruby
|
|
75
|
+
Vehicle.with_state(nil) # Returns all vehicles
|
|
76
|
+
Vehicle.with_state(params[:state]) # Returns all vehicles if params[:state] is nil
|
|
77
|
+
Vehicle.where(color: 'red').with_state(nil) # Returns all red vehicles (chainable)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Rails Enum Integration
|
|
81
|
+
|
|
82
|
+
When your ActiveRecord model uses Rails enums and defines a state machine on the same attribute, this gem automatically detects the conflict and provides seamless integration. This prevents method name collisions between Rails enum methods and state machine methods.
|
|
83
|
+
|
|
84
|
+
### Auto-Detection and Conflict Resolution
|
|
85
|
+
|
|
86
|
+
```ruby
|
|
87
|
+
class Order < ApplicationRecord
|
|
88
|
+
# Rails enum definition
|
|
89
|
+
enum :status, { pending: 0, processing: 1, completed: 2, cancelled: 3 }
|
|
90
|
+
|
|
91
|
+
# State machine on the same attribute
|
|
92
|
+
state_machine :status do
|
|
93
|
+
state :pending, :processing, :completed, :cancelled
|
|
94
|
+
|
|
95
|
+
event :process do
|
|
96
|
+
transition pending: :processing
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
event :complete do
|
|
100
|
+
transition processing: :completed
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
event :cancel do
|
|
104
|
+
transition [:pending, :processing] => :cancelled
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
When enum integration is detected, the gem automatically:
|
|
111
|
+
- Preserves original Rails enum methods (`pending?`, `processing?`, etc.)
|
|
112
|
+
- Generates prefixed state machine methods to avoid conflicts (`status_pending?`, `status_processing?`, etc.)
|
|
113
|
+
- Creates prefixed scope methods (`Order.status_pending`, `Order.status_processing`, etc.)
|
|
114
|
+
|
|
115
|
+
### Available Methods
|
|
116
|
+
|
|
117
|
+
**Original Rails enum methods (preserved):**
|
|
118
|
+
```ruby
|
|
119
|
+
order = Order.create(status: :pending)
|
|
120
|
+
order.pending? # => true (Rails enum method)
|
|
121
|
+
order.processing? # => false (Rails enum method)
|
|
122
|
+
order.processing! # Sets status to :processing (Rails enum method)
|
|
123
|
+
|
|
124
|
+
Order.pending # Rails enum scope
|
|
125
|
+
Order.processing # Rails enum scope
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**Generated state machine methods (prefixed):**
|
|
129
|
+
```ruby
|
|
130
|
+
# Predicate methods
|
|
131
|
+
order.status_pending? # => true (state machine method)
|
|
132
|
+
order.status_processing? # => false (state machine method)
|
|
133
|
+
order.status_completed? # => false (state machine method)
|
|
134
|
+
|
|
135
|
+
# Bang methods (for conflict resolution only)
|
|
136
|
+
# These are placeholders and raise runtime errors
|
|
137
|
+
order.status_processing! # => raises RuntimeError
|
|
138
|
+
|
|
139
|
+
# Scope methods
|
|
140
|
+
Order.status_pending # State machine scope
|
|
141
|
+
Order.status_processing # State machine scope
|
|
142
|
+
Order.not_status_pending # Negative state machine scope
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Introspection API
|
|
146
|
+
|
|
147
|
+
The integration provides a comprehensive introspection API for advanced use cases:
|
|
148
|
+
|
|
149
|
+
```ruby
|
|
150
|
+
machine = Order.state_machine(:status)
|
|
151
|
+
|
|
152
|
+
# Check if enum integration is enabled
|
|
153
|
+
machine.enum_integrated? # => true
|
|
154
|
+
|
|
155
|
+
# Get the Rails enum mapping
|
|
156
|
+
machine.enum_mapping # => {"pending"=>0, "processing"=>1, "completed"=>2, "cancelled"=>3}
|
|
157
|
+
|
|
158
|
+
# Get original Rails enum methods that were preserved
|
|
159
|
+
machine.original_enum_methods
|
|
160
|
+
# => ["pending?", "processing?", "completed?", "cancelled?", "pending!", "processing!", ...]
|
|
161
|
+
|
|
162
|
+
# Get state machine methods that were generated
|
|
163
|
+
machine.state_machine_methods
|
|
164
|
+
# => ["status_pending?", "status_processing?", "status_completed?", "status_cancelled?", ...]
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Integer-backed state attributes
|
|
168
|
+
|
|
169
|
+
Integer columns whose states don't declare explicit values are converted
|
|
170
|
+
transparently: application code reads state names while the database stores
|
|
171
|
+
integers (mapped by definition order).
|
|
172
|
+
|
|
173
|
+
```ruby
|
|
174
|
+
class Order < ApplicationRecord
|
|
175
|
+
state_machine :status, initial: :pending do
|
|
176
|
+
state :pending
|
|
177
|
+
state :approved
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
order = Order.create!
|
|
182
|
+
order.status = :approved
|
|
183
|
+
order.status # => "approved"
|
|
184
|
+
# The database stores 1.
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Machines where every state declares an explicit integer value keep the classic
|
|
188
|
+
raw-integer behavior automatically: reads return the integer and `status_name`
|
|
189
|
+
returns the state name:
|
|
190
|
+
|
|
191
|
+
```ruby
|
|
192
|
+
class LegacyOrder < ApplicationRecord
|
|
193
|
+
self.table_name = "orders"
|
|
194
|
+
|
|
195
|
+
state_machine :status, initial: :pending do
|
|
196
|
+
state :pending, value: 0
|
|
197
|
+
state :approved, value: 1
|
|
198
|
+
|
|
199
|
+
event :approve do
|
|
200
|
+
transition pending: :approved
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
order = LegacyOrder.create!
|
|
206
|
+
order.approve!
|
|
207
|
+
order.status # => 1
|
|
208
|
+
order.status_name # => :approved
|
|
209
|
+
# The database stores 1.
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Applications that want no type conversion at all can disable it during boot,
|
|
213
|
+
before defining affected state machines:
|
|
214
|
+
|
|
215
|
+
```ruby
|
|
216
|
+
# config/initializers/state_machines.rb
|
|
217
|
+
|
|
218
|
+
StateMachines::Integrations::ActiveRecord.auto_convert_integer_state_attributes = false
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
With this setting disabled, integer-backed state attributes are left entirely
|
|
222
|
+
to ActiveRecord's normal integer handling.
|
|
223
|
+
|
|
224
|
+
### Requirements for Enum Integration
|
|
225
|
+
|
|
226
|
+
- The state machine attribute must match an existing Rails enum attribute
|
|
227
|
+
- Auto-detection is enabled by default when this condition is met
|
|
228
|
+
|
|
229
|
+
### Configuration Options
|
|
230
|
+
|
|
231
|
+
The enum integration supports several configuration options:
|
|
232
|
+
|
|
233
|
+
- `prefix` (default: true) - Adds a prefix to generated methods to avoid conflicts
|
|
234
|
+
- `suffix` (default: false) - Alternative naming strategy using suffixes instead of prefixes
|
|
235
|
+
- `scopes` (default: true) - Controls whether state machine scopes are generated
|
|
236
|
+
|
|
237
|
+
## State driven validations
|
|
68
238
|
|
|
69
239
|
As mentioned in `StateMachines::Machine#state`, you can define behaviors,
|
|
70
240
|
like validations, that only execute for certain states. One *important*
|
|
@@ -73,7 +243,7 @@ framework, custom validators will not work as expected when defined to run
|
|
|
73
243
|
in multiple states. For example:
|
|
74
244
|
|
|
75
245
|
```ruby
|
|
76
|
-
class Vehicle <
|
|
246
|
+
class Vehicle < ApplicationRecord
|
|
77
247
|
state_machine do
|
|
78
248
|
state :first_gear, :second_gear do
|
|
79
249
|
validate :speed_is_legal
|
|
@@ -87,7 +257,7 @@ for the <tt>:second_gear</tt> state. To avoid this, you can define your
|
|
|
87
257
|
custom validation like so:
|
|
88
258
|
|
|
89
259
|
```ruby
|
|
90
|
-
class Vehicle <
|
|
260
|
+
class Vehicle < ApplicationRecord
|
|
91
261
|
state_machine do
|
|
92
262
|
state :first_gear, :second_gear do
|
|
93
263
|
validate {|vehicle| vehicle.speed_is_legal}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Use lazy evaluation to avoid circular dependencies with frozen default_messages
|
|
4
|
+
# This ensures messages can be updated after gem loading while maintaining thread safety
|
|
1
5
|
{ en: {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
6
|
+
activerecord: {
|
|
7
|
+
errors: {
|
|
8
|
+
messages: {
|
|
9
|
+
invalid: ->(*) { StateMachines::Machine.default_messages[:invalid] },
|
|
10
|
+
invalid_event: ->(*) { format(StateMachines::Machine.default_messages[:invalid_event], '%<state>s') },
|
|
11
|
+
invalid_transition: ->(*) { format(StateMachines::Machine.default_messages[:invalid_transition], '%<event>s') }
|
|
12
|
+
}
|
|
10
13
|
}
|
|
14
|
+
}
|
|
11
15
|
} }
|
|
12
|
-
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module StateMachines
|
|
4
|
+
module Type
|
|
5
|
+
# Custom ActiveRecord attribute type for state machine attributes backed by
|
|
6
|
+
# integer columns. Handles bidirectional conversion between state name strings
|
|
7
|
+
# (used internally by the state machine) and integer values (stored in the DB).
|
|
8
|
+
#
|
|
9
|
+
# States without explicit integer values are mapped by their index position
|
|
10
|
+
# in the states collection (0, 1, 2, …). States with an explicit integer
|
|
11
|
+
# value (e.g. state :pending, value: 2) use that value directly.
|
|
12
|
+
#
|
|
13
|
+
# When *every* named state has an explicit integer value, the column already
|
|
14
|
+
# stores the canonical state values and no name<->integer conversion is
|
|
15
|
+
# needed. In that case the type delegates to the column's original integer
|
|
16
|
+
# type, preserving the classic raw-integer behavior
|
|
17
|
+
# (e.g. record.status # => 1, record.status_name # => :approved).
|
|
18
|
+
class Integer < ::ActiveRecord::Type::Value
|
|
19
|
+
# The column's original attribute type, exposed so re-registration
|
|
20
|
+
# (e.g. for STI subclasses) can reuse it instead of wrapping this type.
|
|
21
|
+
#
|
|
22
|
+
# @return [ActiveModel::Type::Value]
|
|
23
|
+
attr_reader :raw_type
|
|
24
|
+
|
|
25
|
+
# @param states [StateMachines::StateCollection] live collection of the
|
|
26
|
+
# machine's states; held by reference because states are defined after
|
|
27
|
+
# the type is registered
|
|
28
|
+
# @param raw_type [ActiveModel::Type::Value, nil] the column's original
|
|
29
|
+
# attribute type, used verbatim in passthrough mode so adapter-specific
|
|
30
|
+
# integer behavior (limits, range checks) is preserved
|
|
31
|
+
def initialize(states, raw_type: nil)
|
|
32
|
+
@states = states
|
|
33
|
+
@raw_type = raw_type || ::ActiveModel::Type::Integer.new
|
|
34
|
+
super()
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Converts an integer from the database to a state name string.
|
|
38
|
+
#
|
|
39
|
+
# @param value [Integer, String, nil] raw database value
|
|
40
|
+
# @return [String, Integer, nil] state name, or the original type's value
|
|
41
|
+
# in passthrough mode, or the raw value when no state matches
|
|
42
|
+
def deserialize(value)
|
|
43
|
+
states = named_states
|
|
44
|
+
return @raw_type.deserialize(value) if passthrough?(states)
|
|
45
|
+
return nil if value.nil?
|
|
46
|
+
|
|
47
|
+
int_val = value.to_i
|
|
48
|
+
state = states.detect { |s| state_integer(s, states) == int_val }
|
|
49
|
+
state ? state.name.to_s : value
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Converts an assigned value (symbol, string, or integer) to the in-memory
|
|
53
|
+
# state name string.
|
|
54
|
+
#
|
|
55
|
+
# @param value [Symbol, String, Integer, nil] assigned value
|
|
56
|
+
# @return [String, Integer, nil] state name, or the original type's cast
|
|
57
|
+
# in passthrough mode
|
|
58
|
+
def cast(value)
|
|
59
|
+
states = named_states
|
|
60
|
+
return @raw_type.cast(value) if passthrough?(states)
|
|
61
|
+
return nil if value.nil?
|
|
62
|
+
|
|
63
|
+
state = states.detect { |s| s.name.to_s == value.to_s }
|
|
64
|
+
state ||= states.detect { |s| state_integer(s, states) == value.to_i } if value.respond_to?(:to_i)
|
|
65
|
+
state ? state.name.to_s : value.to_s
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Converts a state name string to its integer for the database write.
|
|
69
|
+
#
|
|
70
|
+
# @param value [String, Symbol, Integer, nil] in-memory value
|
|
71
|
+
# @return [Integer, nil] integer to store
|
|
72
|
+
def serialize(value)
|
|
73
|
+
states = named_states
|
|
74
|
+
return @raw_type.serialize(value) if passthrough?(states)
|
|
75
|
+
return nil if value.nil?
|
|
76
|
+
|
|
77
|
+
state = states.detect { |s| s.name.to_s == value.to_s }
|
|
78
|
+
state ? state_integer(state, states) : value
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# @return [Symbol] the ActiveModel type identifier
|
|
82
|
+
def type
|
|
83
|
+
:integer
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
private
|
|
87
|
+
|
|
88
|
+
# All non-nil states in definition order, not memoized because states are
|
|
89
|
+
# added to the collection after the type is instantiated.
|
|
90
|
+
#
|
|
91
|
+
# @return [Array<StateMachines::State>]
|
|
92
|
+
def named_states
|
|
93
|
+
@states.reject { |s| s.name.nil? }
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Whether the machine was defined for raw integer storage, in which case
|
|
97
|
+
# conversion would change documented behavior. True when every named state
|
|
98
|
+
# declares an explicit integer value. Evaluated lazily on every call
|
|
99
|
+
# because states (and their values) are defined after the type is
|
|
100
|
+
# registered. Uses value(false) so dynamic (Proc) state values are never
|
|
101
|
+
# evaluated for this metadata decision.
|
|
102
|
+
#
|
|
103
|
+
# @param states [Array<StateMachines::State>] pre-computed named states
|
|
104
|
+
# @return [Boolean]
|
|
105
|
+
def passthrough?(states)
|
|
106
|
+
states.any? && states.all? { |s| s.value(false).is_a?(::Integer) }
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# The integer to use for storage: the explicit state value if set
|
|
110
|
+
# (e.g. state :pending, value: 2), otherwise the index position among
|
|
111
|
+
# named states.
|
|
112
|
+
#
|
|
113
|
+
# @param state [StateMachines::State]
|
|
114
|
+
# @param states [Array<StateMachines::State>] pre-computed named states
|
|
115
|
+
# @return [Integer]
|
|
116
|
+
def state_integer(state, states)
|
|
117
|
+
value = state.value(false)
|
|
118
|
+
value.is_a?(::Integer) ? value : states.index(state)
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|