mirror of
https://github.com/aasm/aasm
synced 2023-03-27 23:22:41 -04:00
using default name (all tests green)
This commit is contained in:
parent
7984528e07
commit
eca394bb9b
14 changed files with 193 additions and 154 deletions
|
@ -8,36 +8,47 @@ module AASM
|
|||
|
||||
# do not overwrite existing state machines, which could have been created by
|
||||
# inheritance, see class method inherited
|
||||
AASM::StateMachine[base] ||= AASM::StateMachine.new
|
||||
AASM::StateMachine[base] ||= {}
|
||||
|
||||
AASM::Persistence.load_persistence(base)
|
||||
super
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
|
||||
# make sure inheritance (aka subclassing) works with AASM
|
||||
def inherited(base)
|
||||
AASM::StateMachine[base] = AASM::StateMachine[self].clone
|
||||
AASM::StateMachine[base] = {}
|
||||
AASM::StateMachine[self].keys.each do |state_machine_name|
|
||||
AASM::StateMachine[base][state_machine_name] = AASM::StateMachine[self][state_machine_name].clone
|
||||
end
|
||||
super
|
||||
end
|
||||
|
||||
# this is the entry point for all state and event definitions
|
||||
def aasm(options={}, &block)
|
||||
@aasm ||= AASM::Base.new(self, options)
|
||||
@aasm.instance_eval(&block) if block # new DSL
|
||||
@aasm
|
||||
end
|
||||
def aasm(*args, &block)
|
||||
if args[0].is_a?(Symbol) || args[0].is_a?(String)
|
||||
# using custom name
|
||||
name = args[0].to_sym
|
||||
options = args[1] || {}
|
||||
else
|
||||
# using the default name
|
||||
name = :default
|
||||
options = args[0] || {}
|
||||
end
|
||||
|
||||
# deprecated, remove in version 4.1
|
||||
def aasm_human_event_name(event) # event_name?
|
||||
warn '[DEPRECATION] AASM: aasm_human_event_name is deprecated, use aasm.human_event_name instead'
|
||||
aasm.human_event_name(event)
|
||||
AASM::StateMachine[self][name] ||= AASM::StateMachine.new
|
||||
|
||||
@aasm ||= {}
|
||||
@aasm[name] ||= AASM::Base.new(self, name, AASM::StateMachine[self][name], options)
|
||||
@aasm[name].instance_eval(&block) if block # new DSL
|
||||
@aasm[name]
|
||||
end
|
||||
end # ClassMethods
|
||||
|
||||
def aasm
|
||||
@aasm ||= AASM::InstanceBase.new(self)
|
||||
# this is the entry point for all instance-level access to AASM
|
||||
def aasm(name=:default)
|
||||
@aasm ||= {}
|
||||
@aasm[name.to_sym] ||= AASM::InstanceBase.new(self, name.to_sym)
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -56,10 +67,10 @@ private
|
|||
return args
|
||||
end
|
||||
|
||||
def aasm_fire_event(event_name, options, *args, &block)
|
||||
event = self.class.aasm.state_machine.events[event_name]
|
||||
def aasm_fire_event(state_machine_name, event_name, options, *args, &block)
|
||||
event = self.class.aasm(state_machine_name).state_machine.events[event_name]
|
||||
begin
|
||||
old_state = aasm.state_object_for_name(aasm.current_state)
|
||||
old_state = aasm(state_machine_name).state_object_for_name(aasm(state_machine_name).current_state)
|
||||
|
||||
# new event before callback
|
||||
event.fire_callbacks(
|
||||
|
@ -70,58 +81,58 @@ private
|
|||
|
||||
if may_fire_to = event.may_fire?(self, *args)
|
||||
old_state.fire_callbacks(:before_exit, self,
|
||||
*process_args(event, aasm.current_state, *args))
|
||||
*process_args(event, aasm(state_machine_name).current_state, *args))
|
||||
old_state.fire_callbacks(:exit, self,
|
||||
*process_args(event, aasm.current_state, *args)) # TODO: remove for AASM 4?
|
||||
*process_args(event, aasm(state_machine_name).current_state, *args))
|
||||
|
||||
if new_state_name = event.fire(self, {:may_fire => may_fire_to}, *args)
|
||||
aasm_fired(event, old_state, new_state_name, options, *args, &block)
|
||||
aasm_fired(state_machine_name, event, old_state, new_state_name, options, *args, &block)
|
||||
else
|
||||
aasm_failed(event_name, old_state)
|
||||
aasm_failed(state_machine_name, event_name, old_state)
|
||||
end
|
||||
else
|
||||
aasm_failed(event_name, old_state)
|
||||
aasm_failed(state_machine_name, event_name, old_state)
|
||||
end
|
||||
rescue StandardError => e
|
||||
event.fire_callbacks(:error, self, e, *process_args(event, aasm.current_state, *args)) || raise(e)
|
||||
event.fire_callbacks(:error, self, e, *process_args(event, aasm(state_machine_name).current_state, *args)) || raise(e)
|
||||
end
|
||||
end
|
||||
|
||||
def aasm_fired(event, old_state, new_state_name, options, *args)
|
||||
def aasm_fired(state_machine_name, event, old_state, new_state_name, options, *args)
|
||||
persist = options[:persist]
|
||||
|
||||
new_state = aasm.state_object_for_name(new_state_name)
|
||||
new_state = aasm(state_machine_name).state_object_for_name(new_state_name)
|
||||
|
||||
new_state.fire_callbacks(:before_enter, self,
|
||||
*process_args(event, aasm.current_state, *args))
|
||||
*process_args(event, aasm(state_machine_name).current_state, *args))
|
||||
|
||||
new_state.fire_callbacks(:enter, self,
|
||||
*process_args(event, aasm.current_state, *args)) # TODO: remove for AASM 4?
|
||||
*process_args(event, aasm(state_machine_name).current_state, *args)) # TODO: remove for AASM 4?
|
||||
|
||||
persist_successful = true
|
||||
if persist
|
||||
persist_successful = aasm.set_current_state_with_persistence(new_state_name)
|
||||
persist_successful = aasm(state_machine_name).set_current_state_with_persistence(new_state_name)
|
||||
if persist_successful
|
||||
yield if block_given?
|
||||
event.fire_callbacks(:success, self)
|
||||
end
|
||||
else
|
||||
aasm.current_state = new_state_name
|
||||
aasm(state_machine_name).current_state = new_state_name
|
||||
yield if block_given?
|
||||
end
|
||||
|
||||
if persist_successful
|
||||
old_state.fire_callbacks(:after_exit, self,
|
||||
*process_args(event, aasm.current_state, *args))
|
||||
*process_args(event, aasm(state_machine_name).current_state, *args))
|
||||
new_state.fire_callbacks(:after_enter, self,
|
||||
*process_args(event, aasm.current_state, *args))
|
||||
*process_args(event, aasm(state_machine_name).current_state, *args))
|
||||
event.fire_callbacks(
|
||||
:after,
|
||||
self,
|
||||
*process_args(event, old_state.name, *args)
|
||||
)
|
||||
|
||||
self.aasm_event_fired(event.name, old_state.name, aasm.current_state) if self.respond_to?(:aasm_event_fired)
|
||||
self.aasm_event_fired(event.name, old_state.name, aasm(state_machine_name).current_state) if self.respond_to?(:aasm_event_fired)
|
||||
else
|
||||
self.aasm_event_failed(event.name, old_state.name) if self.respond_to?(:aasm_event_failed)
|
||||
end
|
||||
|
@ -129,13 +140,13 @@ private
|
|||
persist_successful
|
||||
end
|
||||
|
||||
def aasm_failed(event_name, old_state)
|
||||
def aasm_failed(state_machine_name, event_name, old_state)
|
||||
if self.respond_to?(:aasm_event_failed)
|
||||
self.aasm_event_failed(event_name, old_state.name)
|
||||
end
|
||||
|
||||
if AASM::StateMachine[self.class].config.whiny_transitions
|
||||
raise AASM::InvalidTransition.new(self, event_name)
|
||||
if AASM::StateMachine[self.class][state_machine_name].config.whiny_transitions
|
||||
raise AASM::InvalidTransition.new(self, event_name)
|
||||
else
|
||||
false
|
||||
end
|
||||
|
|
|
@ -3,9 +3,11 @@ module AASM
|
|||
|
||||
attr_reader :state_machine
|
||||
|
||||
def initialize(klass, options={}, &block)
|
||||
def initialize(klass, name, state_machine, options={}, &block)
|
||||
@klass = klass
|
||||
@state_machine = AASM::StateMachine[@klass]
|
||||
@name = name
|
||||
# @state_machine = @klass.aasm(@name).state_machine
|
||||
@state_machine = state_machine
|
||||
@state_machine.config.column ||= (options[:column] || :aasm_state).to_sym # aasm4
|
||||
# @state_machine.config.column = options[:column].to_sym if options[:column] # master
|
||||
@options = options
|
||||
|
@ -56,10 +58,16 @@ module AASM
|
|||
def state(name, options={})
|
||||
@state_machine.add_state(name, @klass, options)
|
||||
|
||||
@klass.send(:define_method, "#{name}?") do
|
||||
aasm.current_state == name
|
||||
if @klass.instance_methods.include?("#{name}?")
|
||||
warn "The state name #{name} is already used!"
|
||||
end
|
||||
|
||||
@klass.class_eval <<-EORUBY, __FILE__, __LINE__ + 1
|
||||
def #{name}?
|
||||
aasm(:#{@name}).current_state == :#{name}
|
||||
end
|
||||
EORUBY
|
||||
|
||||
unless @klass.const_defined?("STATE_#{name.upcase}")
|
||||
@klass.const_set("STATE_#{name.upcase}", name)
|
||||
end
|
||||
|
@ -69,22 +77,28 @@ module AASM
|
|||
def event(name, options={}, &block)
|
||||
@state_machine.events[name] = AASM::Core::Event.new(name, options, &block)
|
||||
|
||||
if @klass.instance_methods.include?("may_#{name}?")
|
||||
warn "The event name #{name} is already used!"
|
||||
end
|
||||
|
||||
# an addition over standard aasm so that, before firing an event, you can ask
|
||||
# may_event? and get back a boolean that tells you whether the guard method
|
||||
# on the transition will let this happen.
|
||||
@klass.send(:define_method, "may_#{name}?") do |*args|
|
||||
aasm.may_fire_event?(name, *args)
|
||||
end
|
||||
@klass.class_eval <<-EORUBY, __FILE__, __LINE__ + 1
|
||||
def may_#{name}?(*args)
|
||||
aasm(:#{@name}).may_fire_event?(:#{name}, *args)
|
||||
end
|
||||
|
||||
@klass.send(:define_method, "#{name}!") do |*args, &block|
|
||||
aasm.current_event = "#{name}!".to_sym
|
||||
aasm_fire_event(name, {:persist => true}, *args, &block)
|
||||
end
|
||||
def #{name}!(*args, &block)
|
||||
aasm(:#{@name}).current_event = :#{name}!
|
||||
aasm_fire_event(:#{@name}, :#{name}, {:persist => true}, *args, &block)
|
||||
end
|
||||
|
||||
@klass.send(:define_method, "#{name}") do |*args, &block|
|
||||
aasm.current_event = name.to_sym
|
||||
aasm_fire_event(name, {:persist => false}, *args, &block)
|
||||
end
|
||||
def #{name}(*args, &block)
|
||||
aasm(:#{@name}).current_event = :#{name}
|
||||
aasm_fire_event(:#{@name}, :#{name}, {:persist => false}, *args, &block)
|
||||
end
|
||||
EORUBY
|
||||
end
|
||||
|
||||
def states
|
||||
|
|
|
@ -3,21 +3,22 @@ module AASM
|
|||
|
||||
attr_accessor :from_state, :to_state, :current_event
|
||||
|
||||
def initialize(instance)
|
||||
def initialize(instance, name=:default) # instance of the class including AASM, name of the state machine
|
||||
@instance = instance
|
||||
@name = name
|
||||
end
|
||||
|
||||
def current_state
|
||||
@instance.aasm_read_state
|
||||
@instance.aasm_read_state(@name)
|
||||
end
|
||||
|
||||
def current_state=(state)
|
||||
@instance.aasm_write_state_without_persistence(state)
|
||||
@current_state = state
|
||||
@instance.aasm_write_state_without_persistence(state, @name)
|
||||
# @current_state = state
|
||||
end
|
||||
|
||||
def enter_initial_state
|
||||
state_name = determine_state_name(@instance.class.aasm.initial_state)
|
||||
state_name = determine_state_name(@instance.class.aasm(@name).initial_state)
|
||||
state_object = state_object_for_name(state_name)
|
||||
|
||||
state_object.fire_callbacks(:before_enter, @instance)
|
||||
|
@ -36,17 +37,17 @@ module AASM
|
|||
if options[:permitted]
|
||||
# ugliness level 1000
|
||||
permitted_event_names = events(:permitted => true).map(&:name)
|
||||
transitions = @instance.class.aasm.state_machine.events.values_at(*permitted_event_names).compact.map {|e| e.transitions_from_state(current_state) }
|
||||
transitions = @instance.class.aasm(@name).state_machine.events.values_at(*permitted_event_names).compact.map {|e| e.transitions_from_state(current_state) }
|
||||
tos = transitions.map {|t| t[0] ? t[0].to : nil}.flatten.compact.map(&:to_sym).uniq
|
||||
@instance.class.aasm.states.select {|s| tos.include?(s.name.to_sym)}
|
||||
@instance.class.aasm(@name).states.select {|s| tos.include?(s.name.to_sym)}
|
||||
else
|
||||
@instance.class.aasm.states
|
||||
@instance.class.aasm(@name).states
|
||||
end
|
||||
end
|
||||
|
||||
def events(options={})
|
||||
state = options[:state] || current_state
|
||||
events = @instance.class.aasm.events.select {|e| e.transitions_from_state?(state) }
|
||||
events = @instance.class.aasm(@name).events.select {|e| e.transitions_from_state?(state) }
|
||||
|
||||
if options[:permitted]
|
||||
# filters the results of events_for_current_state so that only those that
|
||||
|
@ -58,7 +59,7 @@ module AASM
|
|||
end
|
||||
|
||||
def state_object_for_name(name)
|
||||
obj = @instance.class.aasm.states.find {|s| s == name}
|
||||
obj = @instance.class.aasm(@name).states.find {|s| s == name}
|
||||
raise AASM::UndefinedState, "State :#{name} doesn't exist" if obj.nil?
|
||||
obj
|
||||
end
|
||||
|
@ -75,7 +76,7 @@ module AASM
|
|||
end
|
||||
|
||||
def may_fire_event?(name, *args)
|
||||
if event = @instance.class.aasm.state_machine.events[name]
|
||||
if event = @instance.class.aasm(@name).state_machine.events[name]
|
||||
!!event.may_fire?(@instance, *args)
|
||||
else
|
||||
false # unknown event
|
||||
|
@ -83,7 +84,7 @@ module AASM
|
|||
end
|
||||
|
||||
def set_current_state_with_persistence(state)
|
||||
save_success = @instance.aasm_write_state(state)
|
||||
save_success = @instance.aasm_write_state(state, @name)
|
||||
self.current_state = state if save_success
|
||||
save_success
|
||||
end
|
||||
|
|
|
@ -80,18 +80,18 @@ module AASM
|
|||
# Foo.find(1).aasm.current_state # => :closed
|
||||
#
|
||||
# NOTE: intended to be called from an event
|
||||
def aasm_write_state(state)
|
||||
old_value = read_attribute(self.class.aasm.attribute_name)
|
||||
aasm_write_attribute state
|
||||
def aasm_write_state(state, name=:default)
|
||||
old_value = read_attribute(self.class.aasm(name).attribute_name)
|
||||
aasm_write_attribute state, name
|
||||
|
||||
success = if aasm_skipping_validations
|
||||
value = aasm_raw_attribute_value state
|
||||
self.class.where(self.class.primary_key => self.id).update_all(self.class.aasm.attribute_name => value) == 1
|
||||
success = if aasm_skipping_validations(name)
|
||||
value = aasm_raw_attribute_value(state, name)
|
||||
self.class.where(self.class.primary_key => self.id).update_all(self.class.aasm(name).attribute_name => value) == 1
|
||||
else
|
||||
self.save
|
||||
end
|
||||
unless success
|
||||
write_attribute(self.class.aasm.attribute_name, old_value)
|
||||
write_attribute(self.class.aasm(name).attribute_name, old_value)
|
||||
return false
|
||||
end
|
||||
|
||||
|
@ -110,17 +110,17 @@ module AASM
|
|||
# Foo.find(1).aasm.current_state # => :closed
|
||||
#
|
||||
# NOTE: intended to be called from an event
|
||||
def aasm_write_state_without_persistence(state)
|
||||
aasm_write_attribute state
|
||||
def aasm_write_state_without_persistence(state, name=:default)
|
||||
aasm_write_attribute(state, name)
|
||||
end
|
||||
|
||||
private
|
||||
def aasm_enum
|
||||
case AASM::StateMachine[self.class].config.enum
|
||||
def aasm_enum(name=:default)
|
||||
case AASM::StateMachine[self.class][name].config.enum
|
||||
when false then nil
|
||||
when true then aasm_guess_enum_method
|
||||
when nil then aasm_guess_enum_method if aasm_column_looks_like_enum
|
||||
else AASM::StateMachine[self.class].config.enum
|
||||
else AASM::StateMachine[self.class][name].config.enum
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -132,17 +132,17 @@ module AASM
|
|||
self.class.aasm.attribute_name.to_s.pluralize.to_sym
|
||||
end
|
||||
|
||||
def aasm_skipping_validations
|
||||
AASM::StateMachine[self.class].config.skip_validation_on_save
|
||||
def aasm_skipping_validations(state_machine_name)
|
||||
AASM::StateMachine[self.class][state_machine_name].config.skip_validation_on_save
|
||||
end
|
||||
|
||||
def aasm_write_attribute(state)
|
||||
write_attribute self.class.aasm.attribute_name, aasm_raw_attribute_value(state)
|
||||
def aasm_write_attribute(state, name=:default)
|
||||
write_attribute(self.class.aasm(name).attribute_name, aasm_raw_attribute_value(state, name))
|
||||
end
|
||||
|
||||
def aasm_raw_attribute_value(state)
|
||||
if aasm_enum
|
||||
self.class.send(aasm_enum)[state]
|
||||
def aasm_raw_attribute_value(state, name=:default)
|
||||
if aasm_enum(name)
|
||||
self.class.send(aasm_enum(name))[state]
|
||||
else
|
||||
state.to_s
|
||||
end
|
||||
|
@ -164,32 +164,36 @@ module AASM
|
|||
# foo.aasm_state # => nil
|
||||
#
|
||||
def aasm_ensure_initial_state
|
||||
# checking via respond_to? does not work in Rails <= 3
|
||||
# if respond_to?(self.class.aasm.attribute_name) && send(self.class.aasm.attribute_name).blank? # Rails 4
|
||||
if attribute_names.include?(self.class.aasm.attribute_name.to_s) && send(self.class.aasm.attribute_name).blank?
|
||||
aasm.enter_initial_state
|
||||
AASM::StateMachine[self.class].keys.each do |state_machine_name|
|
||||
# checking via respond_to? does not work in Rails <= 3
|
||||
# if respond_to?(self.class.aasm(state_machine_name).attribute_name) && send(self.class.aasm(state_machine_name).attribute_name).blank? # Rails 4
|
||||
if attribute_names.include?(self.class.aasm(state_machine_name).attribute_name.to_s) && send(self.class.aasm(state_machine_name).attribute_name).blank?
|
||||
aasm(state_machine_name).enter_initial_state
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def aasm_fire_event(name, options, *args, &block)
|
||||
success = options[:persist] ? self.class.transaction(:requires_new => requires_new?) { super } : super
|
||||
def aasm_fire_event(state_machine_name, name, options, *args, &block)
|
||||
success = options[:persist] ? self.class.transaction(:requires_new => requires_new?(state_machine_name)) { super } : super
|
||||
|
||||
if success && options[:persist]
|
||||
event = self.class.aasm.state_machine.events[name]
|
||||
event = self.class.aasm(state_machine_name).state_machine.events[name]
|
||||
event.fire_callbacks(:after_commit, self)
|
||||
end
|
||||
|
||||
success
|
||||
end
|
||||
|
||||
def requires_new?
|
||||
AASM::StateMachine[self.class].config.requires_new_transaction
|
||||
def requires_new?(state_machine_name)
|
||||
AASM::StateMachine[self.class][state_machine_name].config.requires_new_transaction
|
||||
end
|
||||
|
||||
def aasm_validate_states
|
||||
unless aasm_skipping_validations
|
||||
if aasm.current_state && !aasm.states.include?(aasm.current_state)
|
||||
self.errors.add(AASM::StateMachine[self.class].config.column , "is invalid")
|
||||
AASM::StateMachine[self.class].keys.each do |state_machine_name|
|
||||
unless aasm_skipping_validations(state_machine_name)
|
||||
if aasm(state_machine_name).current_state && !aasm(state_machine_name).states.include?(aasm(state_machine_name).current_state)
|
||||
self.errors.add(AASM::StateMachine[self.class][state_machine_name].config.column , "is invalid")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -32,10 +32,10 @@ module AASM
|
|||
# NOTE: intended to be called from an event
|
||||
#
|
||||
# This allows for nil aasm states - be sure to add validation to your model
|
||||
def aasm_read_state
|
||||
state = send(self.class.aasm.attribute_name)
|
||||
def aasm_read_state(name=:default)
|
||||
state = send(self.class.aasm(name).attribute_name)
|
||||
if new_record?
|
||||
state.blank? ? aasm.determine_state_name(self.class.aasm.initial_state) : state.to_sym
|
||||
state.blank? ? aasm.determine_state_name(self.class.aasm(name).initial_state) : state.to_sym
|
||||
else
|
||||
state.blank? ? nil : state.to_sym
|
||||
end
|
||||
|
@ -55,10 +55,10 @@ module AASM
|
|||
# make sure to create a (named) scope for each state
|
||||
def state_with_scope(name, *args)
|
||||
state_without_scope(name, *args)
|
||||
if AASM::StateMachine[@klass].config.create_scopes && !@klass.respond_to?(name)
|
||||
if @state_machine.config.create_scopes && !@klass.respond_to?(name)
|
||||
if @klass.ancestors.map {|klass| klass.to_s}.include?("ActiveRecord::Base")
|
||||
|
||||
conditions = {"#{@klass.table_name}.#{@klass.aasm.attribute_name}" => name.to_s}
|
||||
conditions = {"#{@klass.table_name}.#{@klass.aasm(@name).attribute_name}" => name.to_s}
|
||||
if ActiveRecord::VERSION::MAJOR >= 3
|
||||
@klass.class_eval do
|
||||
scope name, lambda { where(conditions) }
|
||||
|
@ -69,10 +69,10 @@ module AASM
|
|||
end
|
||||
end
|
||||
elsif @klass.ancestors.map {|klass| klass.to_s}.include?("Mongoid::Document")
|
||||
scope_options = lambda { @klass.send(:where, {@klass.aasm.attribute_name.to_sym => name.to_s}) }
|
||||
scope_options = lambda { @klass.send(:where, {@klass.aasm(@name).attribute_name.to_sym => name.to_s}) }
|
||||
@klass.send(:scope, name, scope_options)
|
||||
elsif @klass.ancestors.map {|klass| klass.to_s}.include?("MongoMapper::Document")
|
||||
conditions = { @klass.aasm.attribute_name.to_sym => name.to_s }
|
||||
conditions = { @klass.aasm(@name).attribute_name.to_sym => name.to_s }
|
||||
@klass.scope(name, lambda { @klass.where(conditions) })
|
||||
end
|
||||
end
|
||||
|
|
|
@ -102,7 +102,7 @@ module AASM
|
|||
# Foo.find(1).aasm.current_state # => :closed
|
||||
#
|
||||
# NOTE: intended to be called from an event
|
||||
def aasm_write_state_without_persistence(state)
|
||||
def aasm_write_state_without_persistence(state, name=:default)
|
||||
aasm_write_attribute state
|
||||
end
|
||||
|
||||
|
@ -124,17 +124,17 @@ module AASM
|
|||
self.class.aasm.attribute_name.to_s.pluralize.to_sym
|
||||
end
|
||||
|
||||
def aasm_skipping_validations
|
||||
AASM::StateMachine[self.class].config.skip_validation_on_save
|
||||
def aasm_skipping_validations(state_machine_name)
|
||||
AASM::StateMachine[self.class][state_machine_name].config.skip_validation_on_save
|
||||
end
|
||||
|
||||
def aasm_write_attribute(state)
|
||||
write_attribute self.class.aasm.attribute_name, aasm_raw_attribute_value(state)
|
||||
def aasm_write_attribute(state, name=:default)
|
||||
write_attribute self.class.aasm(name).attribute_name, aasm_raw_attribute_value(state, name)
|
||||
end
|
||||
|
||||
def aasm_raw_attribute_value(state)
|
||||
if aasm_enum
|
||||
self.class.send(aasm_enum)[state]
|
||||
def aasm_raw_attribute_value(state, name=:default)
|
||||
if aasm_enum(name)
|
||||
self.class.send(aasm_enum(name))[state]
|
||||
else
|
||||
state.to_s
|
||||
end
|
||||
|
@ -156,14 +156,18 @@ module AASM
|
|||
# foo.aasm_state # => nil
|
||||
#
|
||||
def aasm_ensure_initial_state
|
||||
return send("#{self.class.aasm.attribute_name}=", aasm.enter_initial_state.to_s) if send(self.class.aasm.attribute_name).blank?
|
||||
AASM::StateMachine[self.class].keys.each do |state_machine_name|
|
||||
send("#{self.class.aasm(state_machine_name).attribute_name}=", aasm(state_machine_name).enter_initial_state.to_s) if send(self.class.aasm(state_machine_name).attribute_name).blank?
|
||||
end
|
||||
end
|
||||
|
||||
def aasm_validate_states
|
||||
send("#{self.class.aasm.attribute_name}=", aasm.enter_initial_state.to_s) if send(self.class.aasm.attribute_name).blank?
|
||||
unless AASM::StateMachine[self.class].config.skip_validation_on_save
|
||||
if aasm.current_state && !aasm.states.include?(aasm.current_state)
|
||||
self.errors.add(AASM::StateMachine[self.class].config.column , "is invalid")
|
||||
AASM::StateMachine[self.class].keys.each do |state_machine_name|
|
||||
send("#{self.class.aasm(state_machine_name).attribute_name}=", aasm(state_machine_name).enter_initial_state.to_s) if send(self.class.aasm(state_machine_name).attribute_name).blank?
|
||||
unless AASM::StateMachine[self.class][state_machine_name].config.skip_validation_on_save
|
||||
if aasm(state_machine_name).current_state && !aasm(state_machine_name).states.include?(aasm(state_machine_name).current_state)
|
||||
self.errors.add(AASM::StateMachine[self.class][state_machine_name].config.column , "is invalid")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -72,12 +72,12 @@ module AASM
|
|||
# Foo.find(1).aasm.current_state # => :closed
|
||||
#
|
||||
# NOTE: intended to be called from an event
|
||||
def aasm_write_state(state)
|
||||
old_value = read_attribute(self.class.aasm.attribute_name)
|
||||
write_attribute(self.class.aasm.attribute_name, state.to_s)
|
||||
def aasm_write_state(state, name=:default)
|
||||
old_value = read_attribute(self.class.aasm(name).attribute_name)
|
||||
write_attribute(self.class.aasm(name).attribute_name, state.to_s)
|
||||
|
||||
unless self.save(:validate => false)
|
||||
write_attribute(self.class.aasm.attribute_name, old_value)
|
||||
write_attribute(self.class.aasm(name).attribute_name, old_value)
|
||||
return false
|
||||
end
|
||||
|
||||
|
@ -96,8 +96,8 @@ module AASM
|
|||
# Foo.find(1).aasm.current_state # => :closed
|
||||
#
|
||||
# NOTE: intended to be called from an event
|
||||
def aasm_write_state_without_persistence(state)
|
||||
write_attribute(self.class.aasm.attribute_name, state.to_s)
|
||||
def aasm_write_state_without_persistence(state, name=:default)
|
||||
write_attribute(self.class.aasm(name).attribute_name, state.to_s)
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -118,16 +118,18 @@ module AASM
|
|||
# foo.aasm_state # => nil
|
||||
#
|
||||
def aasm_ensure_initial_state
|
||||
send("#{self.class.aasm.attribute_name}=", aasm.enter_initial_state.to_s) if send(self.class.aasm.attribute_name).blank?
|
||||
AASM::StateMachine[self.class].keys.each do |state_machine_name|
|
||||
send("#{self.class.aasm(state_machine_name).attribute_name}=", aasm(state_machine_name).enter_initial_state.to_s) if send(self.class.aasm(state_machine_name).attribute_name).blank?
|
||||
end
|
||||
end
|
||||
end # InstanceMethods
|
||||
|
||||
module NamedScopeMethods
|
||||
def aasm_state_with_named_scope name, options = {}
|
||||
aasm_state_without_named_scope name, options
|
||||
self.named_scope name, :conditions => { "#{table_name}.#{self.aasm.attribute_name}" => name.to_s} unless self.respond_to?(name)
|
||||
end
|
||||
end
|
||||
# module NamedScopeMethods
|
||||
# def aasm_state_with_named_scope name, options = {}
|
||||
# aasm_state_without_named_scope name, options
|
||||
# self.named_scope name, :conditions => { "#{table_name}.#{self.aasm.attribute_name}" => name.to_s} unless self.respond_to?(name)
|
||||
# end
|
||||
# end
|
||||
end
|
||||
end # Persistence
|
||||
end # AASM
|
||||
|
|
|
@ -2,21 +2,22 @@ module AASM
|
|||
module Persistence
|
||||
module PlainPersistence
|
||||
|
||||
def aasm_read_state
|
||||
# may be overwritten by persistence mixins
|
||||
def aasm_read_state(name=:default)
|
||||
# all the following lines behave like @current_state ||= aasm.enter_initial_state
|
||||
current = aasm.instance_variable_get("@current_state")
|
||||
current = aasm(name).instance_variable_get("@current_state_#{name}")
|
||||
return current if current
|
||||
aasm.instance_variable_set("@current_state", aasm.enter_initial_state)
|
||||
aasm(name).instance_variable_set("@current_state_#{name}", aasm.enter_initial_state)
|
||||
end
|
||||
|
||||
# may be overwritten by persistence mixins
|
||||
def aasm_write_state(new_state)
|
||||
def aasm_write_state(new_state, name=:default)
|
||||
true
|
||||
end
|
||||
|
||||
# may be overwritten by persistence mixins
|
||||
def aasm_write_state_without_persistence(new_state)
|
||||
true
|
||||
def aasm_write_state_without_persistence(new_state, name=:default)
|
||||
aasm(name).instance_variable_set("@current_state_#{name}", new_state)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -44,10 +44,10 @@ module AASM
|
|||
# NOTE: intended to be called from an event
|
||||
#
|
||||
# This allows for nil aasm states - be sure to add validation to your model
|
||||
def aasm_read_state
|
||||
state = send(self.class.aasm.attribute_name)
|
||||
def aasm_read_state(name=:default)
|
||||
state = send(self.class.aasm(name).attribute_name)
|
||||
if new? && state.to_s.strip.empty?
|
||||
aasm.determine_state_name(self.class.aasm.initial_state)
|
||||
aasm(name).determine_state_name(self.class.aasm(name).initial_state)
|
||||
elsif state.nil?
|
||||
nil
|
||||
else
|
||||
|
@ -71,9 +71,11 @@ module AASM
|
|||
# foo.aasm_state # => nil
|
||||
#
|
||||
def aasm_ensure_initial_state
|
||||
aasm.enter_initial_state if
|
||||
(new? || values.key?(self.class.aasm.attribute_name)) &&
|
||||
send(self.class.aasm.attribute_name).to_s.strip.empty?
|
||||
AASM::StateMachine[self.class].keys.each do |state_machine_name|
|
||||
aasm(state_machine_name).enter_initial_state if
|
||||
(new? || values.key?(self.class.aasm(state_machine_name).attribute_name)) &&
|
||||
send(self.class.aasm(state_machine_name).attribute_name).to_s.strip.empty?
|
||||
end
|
||||
end
|
||||
|
||||
# Writes <tt>state</tt> to the state column and persists it to the database
|
||||
|
@ -85,8 +87,8 @@ module AASM
|
|||
# Foo[1].aasm.current_state # => :closed
|
||||
#
|
||||
# NOTE: intended to be called from an event
|
||||
def aasm_write_state state
|
||||
aasm_column = self.class.aasm.attribute_name
|
||||
def aasm_write_state state, name=:default
|
||||
aasm_column = self.class.aasm(name).attribute_name
|
||||
update_only({aasm_column => state.to_s}, aasm_column)
|
||||
end
|
||||
|
||||
|
@ -102,8 +104,8 @@ module AASM
|
|||
# Foo[1].aasm.current_state # => :closed
|
||||
#
|
||||
# NOTE: intended to be called from an event
|
||||
def aasm_write_state_without_persistence state
|
||||
send("#{self.class.aasm.attribute_name}=", state.to_s)
|
||||
def aasm_write_state_without_persistence state, name=:default
|
||||
send("#{self.class.aasm(name).attribute_name}=", state.to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,7 +10,7 @@ module AASM
|
|||
(@machines ||= {})[klass.to_s] = machine
|
||||
end
|
||||
|
||||
attr_accessor :states, :events, :initial_state, :config
|
||||
attr_accessor :states, :events, :initial_state, :config, :name
|
||||
|
||||
def initialize
|
||||
@initial_state = nil
|
||||
|
|
|
@ -10,15 +10,15 @@ class ProvidedAndPersistedState < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def aasm_read_state
|
||||
def aasm_read_state(*args)
|
||||
:gamma
|
||||
end
|
||||
|
||||
def aasm_write_state(new_state)
|
||||
def aasm_write_state(new_state, *args)
|
||||
@persisted_store = new_state
|
||||
end
|
||||
|
||||
def aasm_write_state_without_persistence(new_state)
|
||||
def aasm_write_state_without_persistence(new_state, *args)
|
||||
@transient_store = new_state
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,7 +18,7 @@ class ParametrisedEvent
|
|||
end
|
||||
end
|
||||
|
||||
def wear_clothes(shirt_color, trouser_type)
|
||||
def wear_clothes(shirt_color, trouser_type=nil)
|
||||
end
|
||||
|
||||
def condition_hair
|
||||
|
|
|
@ -10,15 +10,15 @@ class ProvidedState
|
|||
end
|
||||
end
|
||||
|
||||
def aasm_read_state
|
||||
def aasm_read_state(*args)
|
||||
:beta
|
||||
end
|
||||
|
||||
def aasm_write_state(new_state)
|
||||
def aasm_write_state(new_state, *args)
|
||||
@persisted_store = new_state
|
||||
end
|
||||
|
||||
def aasm_write_state_without_persistence(new_state)
|
||||
def aasm_write_state_without_persistence(new_state, *args)
|
||||
@transient_store = new_state
|
||||
end
|
||||
end
|
||||
|
|
|
@ -160,7 +160,7 @@ describe "instance methods" do
|
|||
|
||||
gate.aasm_write_state state_sym
|
||||
|
||||
expect(gate).to have_received(:aasm_write_attribute).with(state_sym)
|
||||
expect(gate).to have_received(:aasm_write_attribute).with(state_sym, :default)
|
||||
expect(gate).to_not have_received :write_attribute
|
||||
end
|
||||
end
|
||||
|
@ -170,7 +170,7 @@ describe "instance methods" do
|
|||
it "delegates state update to the helper method" do
|
||||
gate.aasm_write_state_without_persistence state_sym
|
||||
|
||||
expect(gate).to have_received(:aasm_write_attribute).with(state_sym)
|
||||
expect(gate).to have_received(:aasm_write_attribute).with(state_sym, :default)
|
||||
expect(gate).to_not have_received :write_attribute
|
||||
end
|
||||
end
|
||||
|
@ -210,7 +210,7 @@ describe "instance methods" do
|
|||
end
|
||||
|
||||
it "generates attribute value using a helper method" do
|
||||
expect(gate).to have_received(:aasm_raw_attribute_value).with(sym)
|
||||
expect(gate).to have_received(:aasm_raw_attribute_value).with(sym, :default)
|
||||
end
|
||||
|
||||
it "writes attribute to the model" do
|
||||
|
@ -413,7 +413,7 @@ describe 'transitions with persistence' do
|
|||
|
||||
it "should only rollback changes in the main transaction not the nested one" do
|
||||
# change configuration to not require new transaction
|
||||
AASM::StateMachine[Transactor].config.requires_new_transaction = false
|
||||
AASM::StateMachine[Transactor][:default].config.requires_new_transaction = false
|
||||
|
||||
expect(transactor).to be_sleeping
|
||||
expect(worker.status).to eq('sleeping')
|
||||
|
|
Loading…
Reference in a new issue