state_machine 1.0.1 → 1.0.2

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 (120) hide show
  1. data/.gitignore +11 -0
  2. data/.travis.yml +16 -0
  3. data/.yardopts +5 -0
  4. data/Appraisals +260 -0
  5. data/CHANGELOG.rdoc +15 -0
  6. data/Gemfile +3 -0
  7. data/README.rdoc +156 -29
  8. data/Rakefile +31 -57
  9. data/gemfiles/active_model-3.0.0.gemfile +7 -0
  10. data/gemfiles/active_model-3.0.0.gemfile.lock +32 -0
  11. data/gemfiles/active_model-3.0.5.gemfile +7 -0
  12. data/gemfiles/active_model-3.0.5.gemfile.lock +32 -0
  13. data/gemfiles/active_record-2.0.0.gemfile +8 -0
  14. data/gemfiles/active_record-2.0.0.gemfile.lock +30 -0
  15. data/gemfiles/active_record-2.0.5.gemfile +8 -0
  16. data/gemfiles/active_record-2.0.5.gemfile.lock +30 -0
  17. data/gemfiles/active_record-2.1.0.gemfile +8 -0
  18. data/gemfiles/active_record-2.1.0.gemfile.lock +30 -0
  19. data/gemfiles/active_record-2.1.2.gemfile +8 -0
  20. data/gemfiles/active_record-2.1.2.gemfile.lock +30 -0
  21. data/gemfiles/active_record-2.2.3.gemfile +8 -0
  22. data/gemfiles/active_record-2.2.3.gemfile.lock +30 -0
  23. data/gemfiles/active_record-2.3.12.gemfile +8 -0
  24. data/gemfiles/active_record-2.3.12.gemfile.lock +30 -0
  25. data/gemfiles/active_record-3.0.0.gemfile +8 -0
  26. data/gemfiles/active_record-3.0.0.gemfile.lock +44 -0
  27. data/gemfiles/active_record-3.0.5.gemfile +8 -0
  28. data/gemfiles/active_record-3.0.5.gemfile.lock +43 -0
  29. data/gemfiles/data_mapper-0.10.2.gemfile +12 -0
  30. data/gemfiles/data_mapper-0.10.2.gemfile.lock +45 -0
  31. data/gemfiles/data_mapper-0.9.11.gemfile +12 -0
  32. data/gemfiles/data_mapper-0.9.11.gemfile.lock +47 -0
  33. data/gemfiles/data_mapper-0.9.4.gemfile +12 -0
  34. data/gemfiles/data_mapper-0.9.4.gemfile.lock +61 -0
  35. data/gemfiles/data_mapper-0.9.7.gemfile +12 -0
  36. data/gemfiles/data_mapper-0.9.7.gemfile.lock +57 -0
  37. data/gemfiles/data_mapper-1.0.0.gemfile +12 -0
  38. data/gemfiles/data_mapper-1.0.0.gemfile.lock +53 -0
  39. data/gemfiles/data_mapper-1.0.1.gemfile +12 -0
  40. data/gemfiles/data_mapper-1.0.1.gemfile.lock +53 -0
  41. data/gemfiles/data_mapper-1.0.2.gemfile +12 -0
  42. data/gemfiles/data_mapper-1.0.2.gemfile.lock +53 -0
  43. data/gemfiles/data_mapper-1.1.0.gemfile +12 -0
  44. data/gemfiles/data_mapper-1.1.0.gemfile.lock +51 -0
  45. data/gemfiles/default.gemfile +7 -0
  46. data/gemfiles/default.gemfile.lock +24 -0
  47. data/gemfiles/mongo_mapper-0.5.5.gemfile +8 -0
  48. data/gemfiles/mongo_mapper-0.5.5.gemfile.lock +33 -0
  49. data/gemfiles/mongo_mapper-0.5.8.gemfile +8 -0
  50. data/gemfiles/mongo_mapper-0.5.8.gemfile.lock +33 -0
  51. data/gemfiles/mongo_mapper-0.6.0.gemfile +8 -0
  52. data/gemfiles/mongo_mapper-0.6.0.gemfile.lock +33 -0
  53. data/gemfiles/mongo_mapper-0.6.10.gemfile +8 -0
  54. data/gemfiles/mongo_mapper-0.6.10.gemfile.lock +33 -0
  55. data/gemfiles/mongo_mapper-0.7.0.gemfile +8 -0
  56. data/gemfiles/mongo_mapper-0.7.0.gemfile.lock +33 -0
  57. data/gemfiles/mongo_mapper-0.7.5.gemfile +8 -0
  58. data/gemfiles/mongo_mapper-0.7.5.gemfile.lock +36 -0
  59. data/gemfiles/mongo_mapper-0.8.0.gemfile +10 -0
  60. data/gemfiles/mongo_mapper-0.8.0.gemfile.lock +40 -0
  61. data/gemfiles/mongo_mapper-0.8.3.gemfile +10 -0
  62. data/gemfiles/mongo_mapper-0.8.3.gemfile.lock +40 -0
  63. data/gemfiles/mongo_mapper-0.8.4.gemfile +8 -0
  64. data/gemfiles/mongo_mapper-0.8.4.gemfile.lock +38 -0
  65. data/gemfiles/mongo_mapper-0.8.6.gemfile +8 -0
  66. data/gemfiles/mongo_mapper-0.8.6.gemfile.lock +38 -0
  67. data/gemfiles/mongo_mapper-0.9.0.gemfile +7 -0
  68. data/gemfiles/mongo_mapper-0.9.0.gemfile.lock +41 -0
  69. data/gemfiles/mongoid-2.0.0.gemfile +7 -0
  70. data/gemfiles/mongoid-2.0.0.gemfile.lock +42 -0
  71. data/gemfiles/mongoid-2.1.4.gemfile +7 -0
  72. data/gemfiles/mongoid-2.1.4.gemfile.lock +40 -0
  73. data/gemfiles/sequel-2.11.0.gemfile +8 -0
  74. data/gemfiles/sequel-2.11.0.gemfile.lock +28 -0
  75. data/gemfiles/sequel-2.12.0.gemfile +8 -0
  76. data/gemfiles/sequel-2.12.0.gemfile.lock +28 -0
  77. data/gemfiles/sequel-2.8.0.gemfile +8 -0
  78. data/gemfiles/sequel-2.8.0.gemfile.lock +28 -0
  79. data/gemfiles/sequel-3.0.0.gemfile +8 -0
  80. data/gemfiles/sequel-3.0.0.gemfile.lock +28 -0
  81. data/gemfiles/sequel-3.13.0.gemfile +8 -0
  82. data/gemfiles/sequel-3.13.0.gemfile.lock +28 -0
  83. data/gemfiles/sequel-3.14.0.gemfile +8 -0
  84. data/gemfiles/sequel-3.14.0.gemfile.lock +28 -0
  85. data/gemfiles/sequel-3.23.0.gemfile +8 -0
  86. data/gemfiles/sequel-3.23.0.gemfile.lock +28 -0
  87. data/gemfiles/sequel-3.24.0.gemfile +8 -0
  88. data/gemfiles/sequel-3.24.0.gemfile.lock +28 -0
  89. data/lib/state_machine/event.rb +13 -90
  90. data/lib/state_machine/helper_module.rb +17 -0
  91. data/lib/state_machine/integrations/active_model.rb +35 -0
  92. data/lib/state_machine/integrations/active_record.rb +41 -2
  93. data/lib/state_machine/integrations/data_mapper.rb +17 -2
  94. data/lib/state_machine/integrations/mongo_mapper.rb +34 -7
  95. data/lib/state_machine/integrations/mongoid.rb +34 -26
  96. data/lib/state_machine/integrations/mongoid/versions.rb +29 -3
  97. data/lib/state_machine/integrations/sequel.rb +22 -72
  98. data/lib/state_machine/integrations/sequel/versions.rb +87 -6
  99. data/lib/state_machine/machine.rb +279 -19
  100. data/lib/state_machine/state.rb +2 -2
  101. data/lib/state_machine/state_context.rb +133 -0
  102. data/lib/state_machine/version.rb +3 -0
  103. data/state_machine.gemspec +22 -0
  104. data/test/test_helper.rb +1 -3
  105. data/test/unit/branch_test.rb +1 -3
  106. data/test/unit/event_collection_test.rb +3 -3
  107. data/test/unit/event_test.rb +1 -3
  108. data/test/unit/helper_module_test.rb +17 -0
  109. data/test/unit/integrations/active_model_test.rb +0 -4
  110. data/test/unit/integrations/active_record_test.rb +50 -9
  111. data/test/unit/integrations/data_mapper_test.rb +267 -253
  112. data/test/unit/integrations/mongo_mapper_test.rb +47 -15
  113. data/test/unit/integrations/mongoid_test.rb +50 -8
  114. data/test/unit/integrations/sequel_test.rb +10 -6
  115. data/test/unit/machine_test.rb +206 -25
  116. data/test/unit/state_context_test.rb +421 -0
  117. data/test/unit/state_test.rb +20 -3
  118. metadata +303 -128
  119. data/lib/state_machine/condition_proxy.rb +0 -94
  120. data/test/unit/condition_proxy_test.rb +0 -328
@@ -137,7 +137,46 @@ module StateMachine
137
137
  # end
138
138
  #
139
139
  # If using the +save+ action for the machine, this option will be ignored as
140
- # the transaction will be created by ActiveRecord within +save+.
140
+ # the transaction will be created by ActiveRecord within +save+. To avoid
141
+ # this, use a different action like so:
142
+ #
143
+ # class Vehicle < ActiveRecord::Base
144
+ # state_machine :initial => :parked, :use_transactions => false, :action => :save_state do
145
+ # ...
146
+ # end
147
+ #
148
+ # alias_method :save_state, :save
149
+ # end
150
+ #
151
+ # == Validations
152
+ #
153
+ # As mentioned in StateMachine::Machine#state, you can define behaviors,
154
+ # like validations, that only execute for certain states. One *important*
155
+ # caveat here is that, due to a constraint in ActiveRecord's validation
156
+ # framework, custom validators will not work as expected when defined to run
157
+ # in multiple states. For example:
158
+ #
159
+ # class Vehicle < ActiveRecord::Base
160
+ # state_machine do
161
+ # ...
162
+ # state :first_gear, :second_gear do
163
+ # validate :speed_is_legal
164
+ # end
165
+ # end
166
+ # end
167
+ #
168
+ # In this case, the <tt>:speed_is_legal</tt> validation will only get run
169
+ # for the <tt>:second_gear</tt> state. To avoid this, you can define your
170
+ # custom validation like so:
171
+ #
172
+ # class Vehicle < ActiveRecord::Base
173
+ # state_machine do
174
+ # ...
175
+ # state :first_gear, :second_gear do
176
+ # validate {|vehicle| vehicle.speed_is_legal}
177
+ # end
178
+ # end
179
+ # end
141
180
  #
142
181
  # == Validation errors
143
182
  #
@@ -417,7 +456,7 @@ module StateMachine
417
456
  # breaks both ancestor lookups and defined?(super). Need to special-case
418
457
  # the existence of query attribute methods.
419
458
  def owner_class_ancestor_has_method?(scope, method)
420
- scope == :instance && method == "#{name}?" || super
459
+ scope == :instance && method == "#{attribute}?" ? owner_class : super
421
460
  end
422
461
  end
423
462
  end
@@ -137,7 +137,10 @@ module StateMachine
137
137
  #
138
138
  # To turn on transactions:
139
139
  #
140
- # class Vehicle < ActiveRecord::Base
140
+ # class Vehicle
141
+ # include DataMapper::Resource
142
+ # ...
143
+ #
141
144
  # state_machine :initial => :parked, :use_transactions => true do
142
145
  # ...
143
146
  # end
@@ -145,7 +148,18 @@ module StateMachine
145
148
  #
146
149
  # If using the +save+ action for the machine, this option will be ignored as
147
150
  # the transaction behavior will depend on the +save+ implementation within
148
- # DataMapper.
151
+ # DataMapper. To avoid this, use a different action like so:
152
+ #
153
+ # class Vehicle
154
+ # include DataMapper::Resource
155
+ # ...
156
+ #
157
+ # state_machine :initial => :parked, :use_transactions => false, :action => :save_state do
158
+ # ...
159
+ # end
160
+ #
161
+ # alias_method :save_state, :save
162
+ # end
149
163
  #
150
164
  # == Validation errors
151
165
  #
@@ -294,6 +308,7 @@ module StateMachine
294
308
  protected
295
309
  # Initializes class-level extensions and defaults for this machine
296
310
  def after_initialize
311
+ super
297
312
  load_observer_extensions
298
313
  end
299
314
 
@@ -107,6 +107,40 @@ module StateMachine
107
107
  # end
108
108
  # end
109
109
  #
110
+ # == Validations
111
+ #
112
+ # As mentioned in StateMachine::Machine#state, you can define behaviors,
113
+ # like validations, that only execute for certain states. One *important*
114
+ # caveat here is that, due to a constraint in MongoMapper's validation
115
+ # framework, custom validators will not work as expected when defined to run
116
+ # in multiple states. For example:
117
+ #
118
+ # class Vehicle
119
+ # include MongoMapper::Document
120
+ #
121
+ # state_machine do
122
+ # ...
123
+ # state :first_gear, :second_gear do
124
+ # validate :speed_is_legal
125
+ # end
126
+ # end
127
+ # end
128
+ #
129
+ # In this case, the <tt>:speed_is_legal</tt> validation will only get run
130
+ # for the <tt>:second_gear</tt> state. To avoid this, you can define your
131
+ # custom validation like so:
132
+ #
133
+ # class Vehicle
134
+ # include MongoMapper::Document
135
+ #
136
+ # state_machine do
137
+ # ...
138
+ # state :first_gear, :second_gear do
139
+ # validate {|vehicle| vehicle.speed_is_legal}
140
+ # end
141
+ # end
142
+ # end
143
+ #
110
144
  # == Validation errors
111
145
  #
112
146
  # If an event fails to successfully fire because there are no matching
@@ -260,13 +294,6 @@ module StateMachine
260
294
  def define_scope(name, scope)
261
295
  lambda {|model, values| model.query.merge(model.query(scope.call(values)))}
262
296
  end
263
-
264
- # ActiveModel's use of method_missing / respond_to for attribute methods
265
- # breaks both ancestor lookups and defined?(super). Need to special-case
266
- # the existence of query attribute methods.
267
- def owner_class_ancestor_has_method?(scope, method)
268
- scope == :instance && method == "#{name}?" || super
269
- end
270
297
  end
271
298
  end
272
299
  end
@@ -105,6 +105,40 @@ module StateMachine
105
105
  # end
106
106
  # end
107
107
  #
108
+ # == Validations
109
+ #
110
+ # As mentioned in StateMachine::Machine#state, you can define behaviors,
111
+ # like validations, that only execute for certain states. One *important*
112
+ # caveat here is that, due to a constraint in Mongoid's validation
113
+ # framework, custom validators will not work as expected when defined to run
114
+ # in multiple states. For example:
115
+ #
116
+ # class Vehicle
117
+ # include Mongoid::Document
118
+ #
119
+ # state_machine do
120
+ # ...
121
+ # state :first_gear, :second_gear do
122
+ # validate :speed_is_legal
123
+ # end
124
+ # end
125
+ # end
126
+ #
127
+ # In this case, the <tt>:speed_is_legal</tt> validation will only get run
128
+ # for the <tt>:second_gear</tt> state. To avoid this, you can define your
129
+ # custom validation like so:
130
+ #
131
+ # class Vehicle
132
+ # include Mongoid::Document
133
+ #
134
+ # state_machine do
135
+ # ...
136
+ # state :first_gear, :second_gear do
137
+ # validate {|vehicle| vehicle.speed_is_legal}
138
+ # end
139
+ # end
140
+ # end
141
+ #
108
142
  # == Validation errors
109
143
  #
110
144
  # If an event fails to successfully fire because there are no matching
@@ -262,26 +296,7 @@ module StateMachine
262
296
  super
263
297
  end
264
298
 
265
- # Forces the change in state to be recognized regardless of whether the
266
- # state value actually changed
267
- def write(object, attribute, value, *args)
268
- result = super
269
-
270
- if (attribute == :state || attribute == :event && value) && !object.send("#{self.attribute}_changed?")
271
- current = read(object, :state)
272
- object.changes[self.attribute.to_s] = [attribute == :event ? current : value, current]
273
- end
274
-
275
- result
276
- end
277
-
278
299
  protected
279
- # Mongoid uses its own implementation of dirty tracking instead of
280
- # ActiveModel's and doesn't support the #{attribute}_will_change! APIs
281
- def supports_dirty_tracking?(object)
282
- false
283
- end
284
-
285
300
  # Only runs validations on the action if using <tt>:save</tt>
286
301
  def runs_validations_on_action?
287
302
  action == :save
@@ -345,13 +360,6 @@ module StateMachine
345
360
  def define_scope(name, scope)
346
361
  lambda {|model, values| model.criteria.where(scope.call(values))}
347
362
  end
348
-
349
- # ActiveModel's use of method_missing / respond_to for attribute methods
350
- # breaks both ancestor lookups and defined?(super). Need to special-case
351
- # the existence of query attribute methods.
352
- def owner_class_ancestor_has_method?(scope, method)
353
- scope == :instance && method == "#{name}?" || super
354
- end
355
363
  end
356
364
  end
357
365
  end
@@ -1,10 +1,10 @@
1
1
  module StateMachine
2
2
  module Integrations #:nodoc:
3
3
  module Mongoid
4
- # Assumes Mongoid 2.1+ uses ActiveModel 3.1+
5
- version '2.0.x' do
4
+ # Assumes Mongoid 2.2+ uses ActiveModel 3.1+
5
+ version '2.0.x - 2.1.x' do
6
6
  def self.active?
7
- ::Mongoid::VERSION >= '2.0.0' && ::Mongoid::VERSION < '2.1.0'
7
+ ::Mongoid::VERSION >= '2.0.0' && ::Mongoid::VERSION < '2.2.0'
8
8
  end
9
9
 
10
10
  def define_action_hook
@@ -13,6 +13,32 @@ module StateMachine
13
13
  super
14
14
  end
15
15
  end
16
+
17
+ version '2.0.x' do
18
+ def self.active?
19
+ ::Mongoid::VERSION >= '2.0.0' && ::Mongoid::VERSION < '2.1.0'
20
+ end
21
+
22
+ # Forces the change in state to be recognized regardless of whether the
23
+ # state value actually changed
24
+ def write(object, attribute, value, *args)
25
+ result = super
26
+
27
+ if (attribute == :state || attribute == :event && value) && !object.send("#{self.attribute}_changed?")
28
+ current = read(object, :state)
29
+ object.changes[self.attribute.to_s] = [attribute == :event ? current : value, current]
30
+ end
31
+
32
+ result
33
+ end
34
+
35
+ protected
36
+ # Mongoid uses its own implementation of dirty tracking instead of
37
+ # ActiveModel's and doesn't support the #{attribute}_will_change! APIs
38
+ def supports_dirty_tracking?(object)
39
+ false
40
+ end
41
+ end
16
42
  end
17
43
  end
18
44
  end
@@ -135,7 +135,16 @@ module StateMachine
135
135
  # end
136
136
  #
137
137
  # If using the +save+ action for the machine, this option will be ignored as
138
- # the transaction will be created by Sequel within +save+.
138
+ # the transaction will be created by Sequel within +save+. To avoid
139
+ # this, use a different action like so:
140
+ #
141
+ # class Vehicle < Sequel::Model
142
+ # state_machine :initial => :parked, :use_transactions => false, :action => :save_state do
143
+ # ...
144
+ # end
145
+ #
146
+ # alias_method :save_state, :save
147
+ # end
139
148
  #
140
149
  # == Validation errors
141
150
  #
@@ -276,22 +285,9 @@ module StateMachine
276
285
  # initial state of the machine *before* any attributes are set on the
277
286
  # object
278
287
  def define_state_initializer
279
- # Hooks in to attribute initialization to set the states *prior* to
280
- # the attributes being set
281
288
  define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1
282
- # Initializes dynamic states
283
- def initialize(*)
284
- super do |*args|
285
- self.class.state_machines.initialize_states(self, :static => false)
286
- changed_columns.clear
287
- yield(*args) if block_given?
288
- end
289
- end
290
-
291
- # Initializes static states
292
- def set(*)
293
- self.class.state_machines.initialize_states(self, :dynamic => false) if values.empty?
294
- super
289
+ def initialize_set(*)
290
+ self.class.state_machines.initialize_states(self) { super }
295
291
  end
296
292
  end_eval
297
293
  end
@@ -305,70 +301,24 @@ module StateMachine
305
301
  end
306
302
  end
307
303
 
308
- # Adds hooks into validation for automatically firing events. This is
309
- # a bit more complicated than other integrations since Sequel doesn't
310
- # provide an easy way to hook around validation calls
304
+ # Defines validation hooks if the machine's action is to save the model
311
305
  def define_action_helpers
312
306
  super
313
-
314
- if action == :save
315
- define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1
316
- def valid?(*args)
317
- yielded = false
318
- result = self.class.state_machines.transitions(self, :save, :after => false).perform do
319
- yielded = true
320
- super
321
- end
322
-
323
- if yielded || result
324
- result
325
- else
326
- #{handle_validation_failure}
327
- end
328
- end
329
- end_eval
330
- end
307
+ define_validation_hook if action == :save
331
308
  end
332
309
 
333
- # Uses custom hooks for :save actions in order to preserve failure
334
- # behavior within Sequel. This is a bit more complicated than other
335
- # integrations since Sequel doesn't provide an easy way to hook around
336
- # save calls.
337
- def define_action_hook
338
- if action == :save
339
- define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1
340
- def #{action_hook}(*)
341
- yielded = false
342
- result = self.class.state_machines.transitions(self, :save).perform do
343
- yielded = true
344
- super
345
- end
346
-
347
- if yielded || result
348
- result
349
- else
350
- #{handle_save_failure}
351
- end
352
- end
353
- end_eval
354
- else
355
- super
356
- end
310
+ # Adds hooks into validation for automatically firing events
311
+ def define_validation_hook
312
+ define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1
313
+ def around_validation(*)
314
+ self.class.state_machines.transitions(self, :save, :after => false).perform { super }
315
+ end
316
+ end_eval
357
317
  end
358
318
 
359
319
  # Uses internal save hooks if using the :save action
360
320
  def action_hook
361
- action == :save ? :_save : super
362
- end
363
-
364
- # Handles whether validation errors should be raised
365
- def handle_validation_failure
366
- 'raise_on_failure?(args.first || {}) ? raise_hook_failure(:validation) : result'
367
- end
368
-
369
- # Handles how save failures are raised
370
- def handle_save_failure
371
- 'raise_hook_failure(:save)'
321
+ action == :save ? :around_save : super
372
322
  end
373
323
 
374
324
  # Creates a scope for finding records *with* a particular state or
@@ -1,17 +1,70 @@
1
1
  module StateMachine
2
2
  module Integrations #:nodoc:
3
3
  module Sequel
4
- version '2.8.x - 3.13.x' do
4
+ version '2.8.x - 3.23.x' do
5
5
  def self.active?
6
- !defined?(::Sequel::MAJOR) || ::Sequel::MAJOR == 2 || ::Sequel::MAJOR == 3 && ::Sequel::MINOR <= 13
6
+ !defined?(::Sequel::MAJOR) || ::Sequel::MAJOR == 2 || ::Sequel::MAJOR == 3 && ::Sequel::MINOR <= 23
7
7
  end
8
8
 
9
- def handle_validation_failure
10
- 'raise_on_save_failure ? save_failure(:validation) : result'
9
+ def define_state_initializer
10
+ define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1
11
+ def initialize(*)
12
+ super do |*args|
13
+ self.class.state_machines.initialize_states(self, :static => false)
14
+ changed_columns.clear
15
+ yield(*args) if block_given?
16
+ end
17
+ end
18
+
19
+ def set(*)
20
+ self.class.state_machines.initialize_states(self, :dynamic => false) if values.empty?
21
+ super
22
+ end
23
+ end_eval
11
24
  end
12
25
 
13
- def handle_save_failure
14
- 'save_failure(:save)'
26
+ def define_validation_hook
27
+ define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1
28
+ def valid?(*args)
29
+ yielded = false
30
+ result = self.class.state_machines.transitions(self, :save, :after => false).perform do
31
+ yielded = true
32
+ super
33
+ end
34
+
35
+ if yielded || result
36
+ result
37
+ else
38
+ #{handle_validation_failure}
39
+ end
40
+ end
41
+ end_eval
42
+ end
43
+
44
+ def define_action_hook
45
+ if action == :save
46
+ define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1
47
+ def #{action_hook}(*)
48
+ yielded = false
49
+ result = self.class.state_machines.transitions(self, :save).perform do
50
+ yielded = true
51
+ super
52
+ end
53
+
54
+ if yielded || result
55
+ result
56
+ else
57
+ #{handle_save_failure}
58
+ end
59
+ end
60
+ end_eval
61
+ else
62
+ super
63
+ end
64
+ end
65
+
66
+ def action_hook
67
+ action == :save ? :_save : super
15
68
  end
16
69
  end
17
70
 
@@ -31,6 +84,34 @@ module StateMachine
31
84
  dataset.model_classes[nil]
32
85
  end
33
86
  end
87
+
88
+ version '2.8.x - 3.13.x' do
89
+ def self.active?
90
+ !defined?(::Sequel::MAJOR) || ::Sequel::MAJOR == 2 || ::Sequel::MAJOR == 3 && ::Sequel::MINOR <= 13
91
+ end
92
+
93
+ def handle_validation_failure
94
+ 'raise_on_save_failure ? save_failure(:validation) : result'
95
+ end
96
+
97
+ def handle_save_failure
98
+ 'save_failure(:save)'
99
+ end
100
+ end
101
+
102
+ version '3.14.x - 3.23.x' do
103
+ def self.active?
104
+ defined?(::Sequel::MAJOR) && ::Sequel::MAJOR == 3 && ::Sequel::MINOR >= 14 && ::Sequel::MINOR <= 23
105
+ end
106
+
107
+ def handle_validation_failure
108
+ 'raise_on_failure?(args.first || {}) ? raise_hook_failure(:validation) : result'
109
+ end
110
+
111
+ def handle_save_failure
112
+ 'raise_hook_failure(:save)'
113
+ end
114
+ end
34
115
  end
35
116
  end
36
117
  end