Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Do not perform transitions if context method returns false #11

Merged
merged 2 commits into from

2 participants

@zombor

I have a requirement to abort a transition state change on certain conditions. I've patched the transition file, but didn't see any specs for that specific behavior.

Here's the sample code I'm using:

require 'statemachine'

module Job
  class StateMachine
    def self.factory(job)
      state_machine = Statemachine.build do
        state :new do
          event :expire, :expired, :expired?
          event :accept, :booked
          event :cancel, :canceled
        end

        context Context.new(job)
      end

      state_machine.context.statemachine = state_machine
      state_machine.state = job.state

      state_machine
    end

    class Context
      attr_accessor :statemachine

      def initialize(job)
        @job = job
      end

      def expired?
        if @job.start_date_time > Time.now.utc
          return false
        end
      end
    end
  end
end

If the job start date is not in the past, it will not move to the expired state.

@zombor

Apparently there are specs for this. I'll fix them up.

@slagyr
Owner

Thanks for the pull request. I'm curious, have you tried the technique documented here? http://slagyr.github.com/statemachine/example3.html

Was is unsatisfactory?

@zombor

If you mean using on_entry, we did discuss this option, but we are logging all state changes for objects, and didn't want excess noise related to this. We also considered inspecting the objects before performing the state change, but that violates tell don't ask.

@slagyr slagyr merged commit e376ca7 into slagyr:master
@slagyr
Owner

statemachine-2.1.0.gem released.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 14 additions and 7 deletions.
  1. +12 −5 lib/statemachine/transition.rb
  2. +2 −2 spec/spec_helper.rb
View
17 lib/statemachine/transition.rb
@@ -17,12 +17,19 @@ def invoke(origin, statemachine, args)
exits, entries = exits_and_entries(origin, destination)
exits.each { |exited_state| exited_state.exit(args) }
- origin.statemachine.invoke_action(@action, args, "transition action from #{origin} invoked by '#{@event}' event") if @action
+ if @action
+ result = origin.statemachine.invoke_action(@action, args, "transition action from #{origin} invoked by '#{@event}' event") if @action
+ transition = !(result === false)
+ else
+ transition = true
+ end
- terminal_state = entries.last
- terminal_state.activate if terminal_state
+ if transition
+ terminal_state = entries.last
+ terminal_state.activate if terminal_state
- entries.each { |entered_state| entered_state.enter(args) }
+ entries.each { |entered_state| entered_state.enter(args) }
+ end
end
def exits_and_entries(origin, destination)
@@ -61,4 +68,4 @@ def entries_to_destination(exit_state, destination)
end
-end
+end
View
4 spec/spec_helper.rb
@@ -33,12 +33,12 @@ def create_turnstile
@alarm_status = false
@thankyou_status = false
@lock = "@locked = true"
- @unlock = "@locked = false"
+ @unlock = "@locked = false; nil"
@alarm = "@alarm_status = true"
@thankyou = "@thankyou_status = true"
@sm = Statemachine.build do
- trans :locked, :coin, :unlocked, "@locked = false"
+ trans :locked, :coin, :unlocked, "@locked = false; nil"
trans :unlocked, :pass, :locked, "@locked = true"
trans :locked, :pass, :locked, "@alarm_status = true"
trans :unlocked, :coin, :locked, "@thankyou_status = true"
Something went wrong with that request. Please try again.