From ef0eb257158eb52277a8b543a7d238dbaa326303 Mon Sep 17 00:00:00 2001 From: Travis Tilley Date: Fri, 30 Oct 2009 12:17:38 -0400 Subject: [PATCH] restructure, de-nest --- lib/aasm.rb | 8 ++ lib/aasm/aasm.rb | 5 -- lib/aasm/event.rb | 158 ++++++++++++++++----------------- lib/aasm/persistence.rb | 20 ++--- lib/aasm/state.rb | 96 ++++++++++---------- lib/aasm/state_machine.rb | 54 ++++++----- lib/aasm/state_transition.rb | 86 +++++++++--------- lib/aasm/supporting_classes.rb | 6 ++ 8 files changed, 211 insertions(+), 222 deletions(-) create mode 100644 lib/aasm/supporting_classes.rb diff --git a/lib/aasm.rb b/lib/aasm.rb index 09d4a7c..659d1d1 100644 --- a/lib/aasm.rb +++ b/lib/aasm.rb @@ -1 +1,9 @@ +module AASM +end + +require 'ostruct' + +require File.join(File.dirname(__FILE__), 'aasm', 'supporting_classes') +require File.join(File.dirname(__FILE__), 'aasm', 'state_machine') +require File.join(File.dirname(__FILE__), 'aasm', 'persistence') require File.join(File.dirname(__FILE__), 'aasm', 'aasm') diff --git a/lib/aasm/aasm.rb b/lib/aasm/aasm.rb index e92b887..d9284cb 100644 --- a/lib/aasm/aasm.rb +++ b/lib/aasm/aasm.rb @@ -1,8 +1,3 @@ -require File.join(File.dirname(__FILE__), 'event') -require File.join(File.dirname(__FILE__), 'state') -require File.join(File.dirname(__FILE__), 'state_machine') -require File.join(File.dirname(__FILE__), 'persistence') - module AASM class InvalidTransition < RuntimeError end diff --git a/lib/aasm/event.rb b/lib/aasm/event.rb index e4c2cfe..7924c8b 100644 --- a/lib/aasm/event.rb +++ b/lib/aasm/event.rb @@ -1,98 +1,92 @@ -require File.join(File.dirname(__FILE__), 'state_transition') +class AASM::SupportingClasses::Event + attr_reader :name, :success, :options -module AASM - module SupportingClasses - class Event - attr_reader :name, :success, :options + def initialize(name, options = {}, &block) + @name = name + @transitions = [] + update(options, &block) + end - def initialize(name, options = {}, &block) - @name = name - @transitions = [] - update(options, &block) + def fire(obj, to_state=nil, *args) + transitions = @transitions.select { |t| t.from == obj.aasm_current_state } + raise AASM::InvalidTransition, "Event '#{name}' cannot transition from '#{obj.aasm_current_state}'" if transitions.size == 0 + + next_state = nil + transitions.each do |transition| + next if to_state and !Array(transition.to).include?(to_state) + if transition.perform(obj) + next_state = to_state || Array(transition.to).first + transition.execute(obj, *args) + break end + end + next_state + end - def fire(obj, to_state=nil, *args) - transitions = @transitions.select { |t| t.from == obj.aasm_current_state } - raise AASM::InvalidTransition, "Event '#{name}' cannot transition from '#{obj.aasm_current_state}'" if transitions.size == 0 + def transitions_from_state?(state) + @transitions.any? { |t| t.from == state } + end - next_state = nil - transitions.each do |transition| - next if to_state and !Array(transition.to).include?(to_state) - if transition.perform(obj) - next_state = to_state || Array(transition.to).first - transition.execute(obj, *args) - break - end - end - next_state - end + def transitions_from_state(state) + @transitions.select { |t| t.from == state } + end - def transitions_from_state?(state) - @transitions.any? { |t| t.from == state } - end + def all_transitions + @transitions + end - def transitions_from_state(state) - @transitions.select { |t| t.from == state } - end + def call_action(action, record) + action = @options[action] + action.is_a?(Array) ? + action.each {|a| _call_action(a, record)} : + _call_action(action, record) + end - def all_transitions - @transitions - end + def ==(event) + if event.is_a? Symbol + name == event + else + name == event.name + end + end - def call_action(action, record) - action = @options[action] - action.is_a?(Array) ? - action.each {|a| _call_action(a, record)} : - _call_action(action, record) - end + def update(options = {}, &block) + if options.key?(:success) then + @success = options[:success] + end + if block then + instance_eval(&block) + end + @options = options + self + end - def ==(event) - if event.is_a? Symbol - name == event - else - name == event.name - end - end + def execute_success_callback(obj, success = nil) + callback = success || @success + case(callback) + when String, Symbol + obj.send(callback) + when Proc + callback.call(obj) + when Array + callback.each{|meth|self.execute_success_callback(obj, meth)} + end + end - def update(options = {}, &block) - if options.key?(:success) then - @success = options[:success] - end - if block then - instance_eval(&block) - end - @options = options - self - end + private - def execute_success_callback(obj, success = nil) - callback = success || @success - case(callback) - when String, Symbol - obj.send(callback) - when Proc - callback.call(obj) - when Array - callback.each{|meth|self.execute_success_callback(obj, meth)} - end - end + def _call_action(action, record) + case action + when Symbol, String + record.send(action) + when Proc + action.call(record) + end + end - private - - def _call_action(action, record) - case action - when Symbol, String - record.send(action) - when Proc - action.call(record) - end - end - - def transitions(trans_opts) - Array(trans_opts[:from]).each do |s| - @transitions << SupportingClasses::StateTransition.new(trans_opts.merge({:from => s.to_sym})) - end - end + def transitions(trans_opts) + Array(trans_opts[:from]).each do |s| + @transitions << AASM::SupportingClasses::StateTransition.new(trans_opts.merge({:from => s.to_sym})) end end end diff --git a/lib/aasm/persistence.rb b/lib/aasm/persistence.rb index 36fe24a..5704d80 100644 --- a/lib/aasm/persistence.rb +++ b/lib/aasm/persistence.rb @@ -1,16 +1,14 @@ -module AASM - module Persistence +module AASM::Persistence - # Checks to see this class or any of it's superclasses inherit from - # ActiveRecord::Base and if so includes ActiveRecordPersistence - def self.set_persistence(base) - # Use a fancier auto-loading thingy, perhaps. When there are more persistence engines. - hierarchy = base.ancestors.map {|klass| klass.to_s} + # Checks to see this class or any of it's superclasses inherit from + # ActiveRecord::Base and if so includes ActiveRecordPersistence + def self.set_persistence(base) + # Use a fancier auto-loading thingy, perhaps. When there are more persistence engines. + hierarchy = base.ancestors.map {|klass| klass.to_s} - if hierarchy.include?("ActiveRecord::Base") - require File.join(File.dirname(__FILE__), 'persistence', 'active_record_persistence') - base.send(:include, AASM::Persistence::ActiveRecordPersistence) - end + if hierarchy.include?("ActiveRecord::Base") + require File.join(File.dirname(__FILE__), 'persistence', 'active_record_persistence') + base.send(:include, AASM::Persistence::ActiveRecordPersistence) end end end diff --git a/lib/aasm/state.rb b/lib/aasm/state.rb index 655b2e9..58e78f7 100644 --- a/lib/aasm/state.rb +++ b/lib/aasm/state.rb @@ -1,55 +1,51 @@ -module AASM - module SupportingClasses - class State - attr_reader :name, :options +class AASM::SupportingClasses::State + attr_reader :name, :options - def initialize(name, options={}) - @name = name - update(options) - end - - def ==(state) - if state.is_a? Symbol - name == state - else - name == state.name - end - end - - def call_action(action, record) - action = @options[action] - action.is_a?(Array) ? - action.each {|a| _call_action(a, record)} : - _call_action(action, record) - end - - def display_name - @display_name ||= name.to_s.gsub(/_/, ' ').capitalize - end - - def for_select - [display_name, name.to_s] - end - - def update(options = {}) - if options.key?(:display) then - @display_name = options.delete(:display) - end - @options = options - self - end - - private - - def _call_action(action, record) - case action - when Symbol, String - record.send(action) - when Proc - action.call(record) - end - end + def initialize(name, options={}) + @name = name + update(options) + end + def ==(state) + if state.is_a? Symbol + name == state + else + name == state.name end end + + def call_action(action, record) + action = @options[action] + action.is_a?(Array) ? + action.each {|a| _call_action(a, record)} : + _call_action(action, record) + end + + def display_name + @display_name ||= name.to_s.gsub(/_/, ' ').capitalize + end + + def for_select + [display_name, name.to_s] + end + + def update(options = {}) + if options.key?(:display) then + @display_name = options.delete(:display) + end + @options = options + self + end + + private + + def _call_action(action, record) + case action + when Symbol, String + record.send(action) + when Proc + action.call(record) + end + end + end diff --git a/lib/aasm/state_machine.rb b/lib/aasm/state_machine.rb index b38f5c3..92313cf 100644 --- a/lib/aasm/state_machine.rb +++ b/lib/aasm/state_machine.rb @@ -1,36 +1,32 @@ -require 'ostruct' +class AASM::StateMachine + def self.[](*args) + (@machines ||= {})[args] + end -module AASM - class StateMachine - def self.[](*args) - (@machines ||= {})[args] - end + def self.[]=(*args) + val = args.pop + (@machines ||= {})[args] = val + end - def self.[]=(*args) - val = args.pop - (@machines ||= {})[args] = val - end + attr_accessor :states, :events, :initial_state, :config + attr_reader :name - attr_accessor :states, :events, :initial_state, :config - attr_reader :name + def initialize(name) + @name = name + @initial_state = nil + @states = [] + @events = {} + @config = OpenStruct.new + end - def initialize(name) - @name = name - @initial_state = nil - @states = [] - @events = {} - @config = OpenStruct.new - end + def clone + klone = super + klone.states = states.clone + klone.events = events.clone + klone + end - def clone - klone = super - klone.states = states.clone - klone.events = events.clone - klone - end - - def create_state(name, options) - @states << AASM::SupportingClasses::State.new(name, options) unless @states.include?(name) - end + def create_state(name, options) + @states << AASM::SupportingClasses::State.new(name, options) unless @states.include?(name) end end diff --git a/lib/aasm/state_transition.rb b/lib/aasm/state_transition.rb index 8947492..c5dce1d 100644 --- a/lib/aasm/state_transition.rb +++ b/lib/aasm/state_transition.rb @@ -1,50 +1,46 @@ -module AASM - module SupportingClasses - class StateTransition - attr_reader :from, :to, :opts - alias_method :options, :opts +class AASM::SupportingClasses::StateTransition + attr_reader :from, :to, :opts + alias_method :options, :opts - def initialize(opts) - @from, @to, @guard, @on_transition = opts[:from], opts[:to], opts[:guard], opts[:on_transition] - @opts = opts - end - - def perform(obj) - case @guard - when Symbol, String - obj.send(@guard) - when Proc - @guard.call(obj) - else - true - end - end - - def execute(obj, *args) - @on_transition.is_a?(Array) ? - @on_transition.each {|ot| _execute(obj, ot, *args)} : - _execute(obj, @on_transition, *args) - end - - def ==(obj) - @from == obj.from && @to == obj.to - end - - def from?(value) - @from == value - end - - private - - def _execute(obj, on_transition, *args) - case on_transition - when Symbol, String - obj.send(on_transition, *args) - when Proc - on_transition.call(obj, *args) - end - end + def initialize(opts) + @from, @to, @guard, @on_transition = opts[:from], opts[:to], opts[:guard], opts[:on_transition] + @opts = opts + end + def perform(obj) + case @guard + when Symbol, String + obj.send(@guard) + when Proc + @guard.call(obj) + else + true end end + + def execute(obj, *args) + @on_transition.is_a?(Array) ? + @on_transition.each {|ot| _execute(obj, ot, *args)} : + _execute(obj, @on_transition, *args) + end + + def ==(obj) + @from == obj.from && @to == obj.to + end + + def from?(value) + @from == value + end + + private + + def _execute(obj, on_transition, *args) + case on_transition + when Symbol, String + obj.send(on_transition, *args) + when Proc + on_transition.call(obj, *args) + end + end + end diff --git a/lib/aasm/supporting_classes.rb b/lib/aasm/supporting_classes.rb new file mode 100644 index 0000000..145eba5 --- /dev/null +++ b/lib/aasm/supporting_classes.rb @@ -0,0 +1,6 @@ +module AASM::SupportingClasses +end + +require File.join(File.dirname(__FILE__), 'state_transition') +require File.join(File.dirname(__FILE__), 'event') +require File.join(File.dirname(__FILE__), 'state')