state_machine 0.9.0 → 0.9.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.
- data/CHANGELOG.rdoc +7 -0
- data/Rakefile +1 -1
- data/lib/state_machine.rb +2 -2
- data/lib/state_machine/callback.rb +2 -2
- data/lib/state_machine/initializers/rails.rb +0 -2
- data/lib/state_machine/integrations/active_model.rb +2 -2
- data/lib/state_machine/integrations/active_record.rb +1 -0
- data/lib/state_machine/integrations/data_mapper.rb +14 -7
- data/lib/state_machine/transition.rb +62 -36
- data/test/unit/integrations/active_record_test.rb +2 -3
- data/test/unit/integrations/data_mapper_test.rb +6 -2
- metadata +2 -2
data/CHANGELOG.rdoc
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
== master
|
2
2
|
|
3
|
+
== 0.9.1 / 2010-05-02
|
4
|
+
|
5
|
+
* Fix ActiveRecord 2.0.0 - 2.2.3 integrations failing if version info isn't already loaded
|
6
|
+
* Fix integration with dirty attribute tracking on DataMapper 0.10.3
|
7
|
+
* Fix observers failing in ActiveRecord 3.0.0.beta4+ integrations
|
8
|
+
* Fix deprecation warning in Rails 3 railtie [Chris Yuan]
|
9
|
+
|
3
10
|
== 0.9.0 / 2010-04-12
|
4
11
|
|
5
12
|
* Use attribute-based event transitions whenever possible to ensure consistency
|
data/Rakefile
CHANGED
@@ -6,7 +6,7 @@ require 'rake/gempackagetask'
|
|
6
6
|
|
7
7
|
spec = Gem::Specification.new do |s|
|
8
8
|
s.name = 'state_machine'
|
9
|
-
s.version = '0.9.
|
9
|
+
s.version = '0.9.1'
|
10
10
|
s.platform = Gem::Platform::RUBY
|
11
11
|
s.summary = 'Adds support for creating state machines for attributes on any Ruby class'
|
12
12
|
s.description = s.summary
|
data/lib/state_machine.rb
CHANGED
@@ -295,8 +295,8 @@ module StateMachine
|
|
295
295
|
#
|
296
296
|
# Within the +state_machine+ block, you can also define callbacks for
|
297
297
|
# transitions. For more information about defining these callbacks,
|
298
|
-
# see StateMachine::Machine#before_transition
|
299
|
-
# StateMachine::Machine#
|
298
|
+
# see StateMachine::Machine#before_transition, StateMachine::Machine#after_transition,
|
299
|
+
# and StateMachine::Machine#around_transition.
|
300
300
|
#
|
301
301
|
# == Namespaces
|
302
302
|
#
|
@@ -204,8 +204,8 @@ module StateMachine
|
|
204
204
|
def bound_method(block)
|
205
205
|
type = self.type
|
206
206
|
arity = block.arity
|
207
|
-
arity += 1 if arity >= 0
|
208
|
-
arity += 1 if arity == 1 && type == :around
|
207
|
+
arity += 1 if arity >= 0 # Make sure the object gets passed
|
208
|
+
arity += 1 if arity == 1 && type == :around # Make sure the block gets passed
|
209
209
|
|
210
210
|
method = if RUBY_VERSION >= '1.9'
|
211
211
|
lambda do |object, *args|
|
@@ -397,14 +397,14 @@ module StateMachine
|
|
397
397
|
["#{type}_#{event}", "#{type}_transition_#{name}"].each do |event_segment|
|
398
398
|
["_from_#{from}", nil].each do |from_segment|
|
399
399
|
["_to_#{to}", nil].each do |to_segment|
|
400
|
-
object.class.changed
|
400
|
+
object.class.changed if object.class.respond_to?(:changed)
|
401
401
|
object.class.notify_observers([event_segment, from_segment, to_segment].join, object, transition)
|
402
402
|
end
|
403
403
|
end
|
404
404
|
end
|
405
405
|
|
406
406
|
# Generic updates
|
407
|
-
object.class.changed
|
407
|
+
object.class.changed if object.class.respond_to?(:changed)
|
408
408
|
object.class.notify_observers("#{type}_transition", object, transition)
|
409
409
|
|
410
410
|
true
|
@@ -261,18 +261,25 @@ module StateMachine
|
|
261
261
|
# Forces the change in state to be recognized regardless of whether the
|
262
262
|
# state value actually changed
|
263
263
|
def write(object, attribute, value)
|
264
|
-
|
265
|
-
|
266
|
-
if ::DataMapper::VERSION =~ /^0
|
264
|
+
if attribute == :state
|
265
|
+
# Force to Dirty state in 0.10.3+
|
266
|
+
if !(::DataMapper::VERSION =~ /^0\.(9\.|10\.[0-2]$)/)
|
267
|
+
object.persisted_state = ::DataMapper::Resource::State::Dirty.new(object) if object.persisted_state.is_a?(::DataMapper::Resource::State::Clean)
|
268
|
+
end
|
269
|
+
|
270
|
+
result = super
|
271
|
+
|
272
|
+
# Change original attributes in 0.9.4 - 0.10.2
|
273
|
+
if ::DataMapper::VERSION =~ /^0\.9\./
|
267
274
|
object.original_values[self.attribute] = "#{value}-ignored" if object.original_values[self.attribute] == value
|
268
|
-
|
269
|
-
# Force the resource's state to Dirty for 0.10.13+
|
270
|
-
object.persisted_state = ::DataMapper::Resource::State::Dirty.new(object) unless ::DataMapper::VERSION =~ /^0\.10\.[0-2]$/ || object.persisted_state.respond_to?(:original_attributes)
|
271
|
-
|
275
|
+
elsif ::DataMapper::VERSION =~ /^0\.10\.[0-2]$/
|
272
276
|
property = owner_class.properties[self.attribute]
|
273
277
|
object.original_attributes[property] = "#{value}-ignored" unless object.original_attributes.include?(property)
|
274
278
|
end
|
279
|
+
else
|
280
|
+
result = super
|
275
281
|
end
|
282
|
+
|
276
283
|
result
|
277
284
|
end
|
278
285
|
|
@@ -167,23 +167,12 @@ module StateMachine
|
|
167
167
|
options = {:after => true}.merge(options)
|
168
168
|
@success = false
|
169
169
|
|
170
|
-
|
171
|
-
# any around callbacks.
|
172
|
-
begin
|
173
|
-
halted = !catch(:halt) { before(options[:after], &block); true }
|
174
|
-
rescue Exception => error
|
175
|
-
raise unless @after_block
|
176
|
-
end
|
170
|
+
halted = pausable { before(options[:after], &block) }
|
177
171
|
|
178
172
|
# After callbacks are only run if:
|
179
|
-
# * There isn't an after block already running
|
180
173
|
# * An around callback didn't halt after yielding
|
181
174
|
# * They're enabled or the run didn't succeed
|
182
|
-
if @
|
183
|
-
@after_block.call(halted, error)
|
184
|
-
elsif !(@before_run && halted) && (options[:after] || !@success)
|
185
|
-
after
|
186
|
-
end
|
175
|
+
after if !(@before_run && halted) && (options[:after] || !@success)
|
187
176
|
|
188
177
|
@before_run
|
189
178
|
end
|
@@ -247,7 +236,7 @@ module StateMachine
|
|
247
236
|
# the state has already been persisted
|
248
237
|
def reset
|
249
238
|
@before_run = @persisted = @after_run = false
|
250
|
-
@
|
239
|
+
@paused_block = nil
|
251
240
|
end
|
252
241
|
|
253
242
|
# Generates a nicely formatted description of this transitions's contents.
|
@@ -261,6 +250,57 @@ module StateMachine
|
|
261
250
|
end
|
262
251
|
|
263
252
|
private
|
253
|
+
# Runs a block that may get paused. If the block doesn't pause, then
|
254
|
+
# execution will continue as normal. If the block gets paused, then it
|
255
|
+
# will take care of switching the execution context when it's resumed.
|
256
|
+
#
|
257
|
+
# This will return true if the given block halts for a reason other than
|
258
|
+
# getting paused.
|
259
|
+
def pausable
|
260
|
+
begin
|
261
|
+
halted = !catch(:halt) { yield; true }
|
262
|
+
rescue Exception => error
|
263
|
+
raise unless @resume_block
|
264
|
+
end
|
265
|
+
|
266
|
+
if @resume_block
|
267
|
+
@resume_block.call(halted, error)
|
268
|
+
else
|
269
|
+
halted
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
# Pauses the current callback execution. This should only occur within
|
274
|
+
# around callbacks when the remainder of the callback will be executed at
|
275
|
+
# a later point in time.
|
276
|
+
def pause
|
277
|
+
unless @resume_block
|
278
|
+
require 'continuation' unless defined?(callcc)
|
279
|
+
callcc do |block|
|
280
|
+
@paused_block = block
|
281
|
+
throw :halt, true
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
# Resumes the execution of a previously paused callback execution. Once
|
287
|
+
# the paused callbacks complete, the current execution will continue.
|
288
|
+
def resume
|
289
|
+
if @paused_block
|
290
|
+
halted, error = callcc do |block|
|
291
|
+
@resume_block = block
|
292
|
+
@paused_block.call
|
293
|
+
end
|
294
|
+
|
295
|
+
@resume_block = @paused_block = nil
|
296
|
+
|
297
|
+
raise error if error
|
298
|
+
!halted
|
299
|
+
else
|
300
|
+
true
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
264
304
|
# Runs the machine's +before+ callbacks for this transition. Only
|
265
305
|
# callbacks that are configured to match the event, from state, and to
|
266
306
|
# state will be invoked.
|
@@ -278,16 +318,12 @@ module StateMachine
|
|
278
318
|
# * The block fails and the callback doesn't run on failures OR
|
279
319
|
# * The block succeeds, but after callbacks are disabled (in which
|
280
320
|
# case a continuation is stored for later execution)
|
281
|
-
return if catch(:
|
321
|
+
return if catch(:cancel) do
|
282
322
|
callback.call(object, context, self) do
|
283
323
|
before(complete, index, &block)
|
284
324
|
|
285
|
-
if @success && !complete
|
286
|
-
|
287
|
-
callcc {|block| @around_block = block}
|
288
|
-
end
|
289
|
-
|
290
|
-
throw :pause, true if @around_block && !@after_block || !callback.matches_success?(@success)
|
325
|
+
pause if @success && !complete
|
326
|
+
throw :cancel, true unless callback.matches_success?(@success)
|
291
327
|
end
|
292
328
|
end
|
293
329
|
else
|
@@ -318,22 +354,12 @@ module StateMachine
|
|
318
354
|
# should never halt the execution of a +perform+.
|
319
355
|
def after
|
320
356
|
unless @after_run
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
@around_block.call
|
327
|
-
end
|
328
|
-
|
329
|
-
@after_block = @around_block = nil
|
330
|
-
raise error if error
|
331
|
-
throw :halt if halted
|
357
|
+
# First resume previously paused callbacks
|
358
|
+
if resume
|
359
|
+
catch(:halt) do
|
360
|
+
after_context = context.merge(:success => @success)
|
361
|
+
machine.callbacks[:after].each {|callback| callback.call(object, after_context, self)}
|
332
362
|
end
|
333
|
-
|
334
|
-
# Call normal after callbacks in order
|
335
|
-
after_context = context.merge(:success => @success)
|
336
|
-
machine.callbacks[:after].each {|callback| callback.call(object, after_context, self)}
|
337
363
|
end
|
338
364
|
|
339
365
|
@after_run = true
|
@@ -12,10 +12,9 @@ FIXTURES_ROOT = File.dirname(__FILE__) + '/../../fixtures/'
|
|
12
12
|
require 'active_support/test_case'
|
13
13
|
require 'active_record/fixtures'
|
14
14
|
|
15
|
-
|
16
|
-
if ActiveRecord::VERSION::STRING >= '2.1.0'
|
15
|
+
begin
|
17
16
|
require 'active_record/test_case'
|
18
|
-
|
17
|
+
rescue LoadError
|
19
18
|
class ActiveRecord::TestCase < ActiveSupport::TestCase
|
20
19
|
self.fixture_path = FIXTURES_ROOT
|
21
20
|
self.use_instantiated_fixtures = false
|
@@ -512,7 +512,9 @@ module DataMapperTest
|
|
512
512
|
end
|
513
513
|
|
514
514
|
def test_should_track_attribute_change
|
515
|
-
if Gem::Version.new(::DataMapper::VERSION) >= Gem::Version.new('0.10.
|
515
|
+
if Gem::Version.new(::DataMapper::VERSION) >= Gem::Version.new('0.10.3')
|
516
|
+
assert_equal e = {@resource.properties[:state] => 'parked'}, @record.original_attributes
|
517
|
+
elsif Gem::Version.new(::DataMapper::VERSION) >= Gem::Version.new('0.10.0')
|
516
518
|
assert_equal e = {@resource.properties[:state] => 'parked-ignored'}, @record.original_attributes
|
517
519
|
else
|
518
520
|
assert_equal e = {:state => 'parked-ignored'}, @record.original_values
|
@@ -580,7 +582,9 @@ module DataMapperTest
|
|
580
582
|
end
|
581
583
|
|
582
584
|
def test_should_track_attribute_changes
|
583
|
-
if Gem::Version.new(::DataMapper::VERSION) >= Gem::Version.new('0.10.
|
585
|
+
if Gem::Version.new(::DataMapper::VERSION) >= Gem::Version.new('0.10.3')
|
586
|
+
assert_equal e = {@resource.properties[:status] => 'parked'}, @record.original_attributes
|
587
|
+
elsif Gem::Version.new(::DataMapper::VERSION) >= Gem::Version.new('0.10.0')
|
584
588
|
assert_equal e = {@resource.properties[:status] => 'parked-ignored'}, @record.original_attributes
|
585
589
|
else
|
586
590
|
assert_equal e = {:status => 'parked-ignored'}, @record.original_values
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: state_machine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Pfeifer
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-
|
12
|
+
date: 2010-05-02 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|