Skip to content

Commit

Permalink
make sure to use parameterised aasm everywhere
Browse files Browse the repository at this point in the history
  • Loading branch information
alto committed May 13, 2015
1 parent c83a3c4 commit 7b15b01
Show file tree
Hide file tree
Showing 12 changed files with 86 additions and 58 deletions.
18 changes: 9 additions & 9 deletions lib/aasm/aasm.rb
Expand Up @@ -28,20 +28,20 @@ def inherited(base)
def aasm(*args, &block)
if args[0].is_a?(Symbol) || args[0].is_a?(String)
# using custom name
name = args[0].to_sym
state_machine_name = args[0].to_sym
options = args[1] || {}
else
# using the default name
name = :default
# using the default state_machine_name
state_machine_name = :default
options = args[0] || {}
end

AASM::StateMachine[self][name] ||= AASM::StateMachine.new
AASM::StateMachine[self][state_machine_name] ||= AASM::StateMachine.new(state_machine_name)

@aasm ||= {}
@aasm[name] ||= AASM::Base.new(self, name, AASM::StateMachine[self][name], options)
@aasm[name].instance_eval(&block) if block # new DSL
@aasm[name]
@aasm[state_machine_name] ||= AASM::Base.new(self, state_machine_name, AASM::StateMachine[self][state_machine_name], options)
@aasm[state_machine_name].instance_eval(&block) if block # new DSL
@aasm[state_machine_name]
end
end # ClassMethods

Expand Down Expand Up @@ -76,7 +76,7 @@ def aasm_fire_event(state_machine_name, event_name, options, *args, &block)
event.fire_callbacks(
:before,
self,
*process_args(event, aasm.current_state, *args)
*process_args(event, aasm(state_machine_name).current_state, *args)
)

if may_fire_to = event.may_fire?(self, *args)
Expand Down Expand Up @@ -146,7 +146,7 @@ def aasm_failed(state_machine_name, event_name, old_state)
end

if AASM::StateMachine[self.class][state_machine_name].config.whiny_transitions
raise AASM::InvalidTransition.new(self, event_name)
raise AASM::InvalidTransition.new(self, event_name, state_machine_name)
else
false
end
Expand Down
2 changes: 1 addition & 1 deletion lib/aasm/base.rb
Expand Up @@ -75,7 +75,7 @@ def #{name}?

# define an event
def event(name, options={}, &block)
@state_machine.events[name] = AASM::Core::Event.new(name, options, &block)
@state_machine.add_event(name, options, &block)

if @klass.instance_methods.include?("may_#{name}?")
warn "The event name #{name} is already used!"
Expand Down
11 changes: 6 additions & 5 deletions lib/aasm/core/event.rb
Expand Up @@ -2,10 +2,11 @@ module AASM::Core
class Event
include DslHelper

attr_reader :name, :options
attr_reader :name, :state_machine, :options

def initialize(name, options = {}, &block)
def initialize(name, state_machine, options = {}, &block)
@name = name
@state_machine = state_machine
@transitions = []
@guards = Array(options[:guard] || options[:guards] || options[:if])
@unless = Array(options[:unless]) #TODO: This could use a better name
Expand Down Expand Up @@ -61,11 +62,11 @@ def transitions(definitions=nil, &block)
if definitions # define new transitions
# Create a separate transition for each from-state to the given state
Array(definitions[:from]).each do |s|
@transitions << AASM::Core::Transition.new(attach_event_guards(definitions.merge(:from => s.to_sym)), &block)
@transitions << AASM::Core::Transition.new(self, attach_event_guards(definitions.merge(:from => s.to_sym)), &block)
end
# Create a transition if :to is specified without :from (transitions from ANY state)
if @transitions.empty? && definitions[:to]
@transitions << AASM::Core::Transition.new(attach_event_guards(definitions), &block)
@transitions << AASM::Core::Transition.new(self, attach_event_guards(definitions), &block)
end
end
@transitions
Expand All @@ -89,7 +90,7 @@ def attach_event_guards(definitions)
def _fire(obj, options={}, to_state=nil, *args)
result = options[:test_only] ? false : nil
if @transitions.map(&:from).any?
transitions = @transitions.select { |t| t.from == obj.aasm.current_state }
transitions = @transitions.select { |t| t.from == obj.aasm(state_machine.name).current_state }
return result if transitions.size == 0
else
transitions = @transitions
Expand Down
5 changes: 3 additions & 2 deletions lib/aasm/core/state.rb
@@ -1,10 +1,11 @@
module AASM::Core
class State
attr_reader :name, :options
attr_reader :name, :state_machine, :options

def initialize(name, klass, options={})
def initialize(name, klass, state_machine, options={})
@name = name
@klass = klass
@state_machine = state_machine
update(options)
end

Expand Down
9 changes: 5 additions & 4 deletions lib/aasm/core/transition.rb
Expand Up @@ -2,12 +2,13 @@ module AASM::Core
class Transition
include DslHelper

attr_reader :from, :to, :opts
attr_reader :from, :to, :event, :opts
alias_method :options, :opts

def initialize(opts, &block)
def initialize(event, opts, &block)
add_options_from_dsl(opts, [:on_transition, :guard, :after], &block) if block

@event = event
@from = opts[:from]
@to = opts[:to]
@guards = Array(opts[:guards]) + Array(opts[:guard]) + Array(opts[:if])
Expand Down Expand Up @@ -44,8 +45,8 @@ def from?(value)

def invoke_callbacks_compatible_with_guard(code, record, args, options={})
if record.respond_to?(:aasm)
record.aasm.from_state = @from if record.aasm.respond_to?(:from_state=)
record.aasm.to_state = @to if record.aasm.respond_to?(:to_state=)
record.aasm(event.state_machine.name).from_state = @from if record.aasm(event.state_machine.name).respond_to?(:from_state=)
record.aasm(event.state_machine.name).to_state = @to if record.aasm(event.state_machine.name).respond_to?(:to_state=)
end

case code
Expand Down
9 changes: 5 additions & 4 deletions lib/aasm/errors.rb
@@ -1,13 +1,14 @@
module AASM

class InvalidTransition < RuntimeError
attr_reader :object, :event_name
def initialize(object, event_name)
@object, @event_name = object, event_name
attr_reader :object, :event_name, :state_machine_name

def initialize(object, event_name, state_machine_name)
@object, @event_name, @state_machine_name = object, event_name, state_machine_name
end

def message
"Event '#{event_name}' cannot transition from '#{object.aasm.current_state}'"
"Event '#{event_name}' cannot transition from '#{object.aasm(state_machine_name).current_state}'"
end
end

Expand Down
2 changes: 1 addition & 1 deletion lib/aasm/instance_base.rb
Expand Up @@ -30,7 +30,7 @@ def enter_initial_state
end

def human_state
AASM::Localizer.new.human_state_name(@instance.class, current_state)
AASM::Localizer.new.human_state_name(@instance.class, state_object_for_name(current_state))
end

def states(options={})
Expand Down
2 changes: 1 addition & 1 deletion lib/aasm/localizer.rb
Expand Up @@ -21,7 +21,7 @@ def human_state_name(klass, state)

def item_for(klass, state, ancestor, options={})
separator = options[:old_style] ? '.' : '/'
:"#{i18n_scope(klass)}.attributes.#{i18n_klass(ancestor)}.#{klass.aasm.attribute_name}#{separator}#{state}"
:"#{i18n_scope(klass)}.attributes.#{i18n_klass(ancestor)}.#{klass.aasm(state.state_machine.name).attribute_name}#{separator}#{state}"
end

def translate_queue(checklist)
Expand Down
15 changes: 10 additions & 5 deletions lib/aasm/state_machine.rb
Expand Up @@ -12,11 +12,12 @@ def self.[]=(klass, machine)

attr_accessor :states, :events, :initial_state, :config, :name

def initialize
def initialize(name)
@initial_state = nil
@states = []
@events = {}
@config = AASM::Configuration.new
@name = name
end

# called internally by Ruby 1.9 after clone()
Expand All @@ -26,13 +27,17 @@ def initialize_copy(orig)
@events = @events.dup
end

def add_state(name, klass, options)
set_initial_state(name, options)
def add_state(state_name, klass, options)
set_initial_state(state_name, options)

# allow reloading, extending or redefining a state
@states.delete(name) if @states.include?(name)
@states.delete(state_name) if @states.include?(state_name)

@states << AASM::Core::State.new(name, klass, options)
@states << AASM::Core::State.new(state_name, klass, self, options)
end

def add_event(name, options, &block)
@events[name] = AASM::Core::Event.new(name, self, options, &block)
end

private
Expand Down
17 changes: 11 additions & 6 deletions spec/unit/event_spec.rb
@@ -1,8 +1,9 @@
require 'spec_helper'

describe 'adding an event' do
let(:state_machine) { AASM::StateMachine.new(:name) }
let(:event) do
AASM::Core::Event.new(:close_order, {:success => :success_callback}) do
AASM::Core::Event.new(:close_order, state_machine, {:success => :success_callback}) do
before :before_callback
after :after_callback
transitions :to => :closed, :from => [:open, :received]
Expand Down Expand Up @@ -35,8 +36,9 @@
end

describe 'transition inspection' do
let(:state_machine) { AASM::StateMachine.new(:name) }
let(:event) do
AASM::Core::Event.new(:run) do
AASM::Core::Event.new(:run, state_machine) do
transitions :to => :running, :from => :sleeping
end
end
Expand All @@ -59,8 +61,9 @@
end

describe 'transition inspection without from' do
let(:state_machine) { AASM::StateMachine.new(:name) }
let(:event) do
AASM::Core::Event.new(:run) do
AASM::Core::Event.new(:run, state_machine) do
transitions :to => :running
end
end
Expand All @@ -76,15 +79,17 @@
end

describe 'firing an event' do
let(:state_machine) { AASM::StateMachine.new(:name) }

it 'should return nil if the transitions are empty' do
obj = double('object', :aasm => double('aasm', :current_state => 'open'))

event = AASM::Core::Event.new(:event)
event = AASM::Core::Event.new(:event, state_machine)
expect(event.fire(obj)).to be_nil
end

it 'should return the state of the first matching transition it finds' do
event = AASM::Core::Event.new(:event) do
event = AASM::Core::Event.new(:event, state_machine) do
transitions :to => :closed, :from => [:open, :received]
end

Expand All @@ -94,7 +99,7 @@
end

it 'should call the guard with the params passed in' do
event = AASM::Core::Event.new(:event) do
event = AASM::Core::Event.new(:event, state_machine) do
transitions :to => :closed, :from => [:open, :received], :guard => :guard_fn
end

Expand Down
4 changes: 3 additions & 1 deletion spec/unit/state_spec.rb
@@ -1,13 +1,15 @@
require 'spec_helper'

describe AASM::Core::State do
let(:state_machine) { AASM::StateMachine.new(:name) }

before(:each) do
@name = :astate
@options = { :crazy_custom_key => 'key' }
end

def new_state(options={})
AASM::Core::State.new(@name, Conversation, @options.merge(options))
AASM::Core::State.new(@name, Conversation, state_machine, @options.merge(options))
end

it 'should set the name' do
Expand Down

0 comments on commit 7b15b01

Please sign in to comment.