aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel/lib/active_model/state_machine/event.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activemodel/lib/active_model/state_machine/event.rb')
-rw-r--r--activemodel/lib/active_model/state_machine/event.rb67
1 files changed, 67 insertions, 0 deletions
diff --git a/activemodel/lib/active_model/state_machine/event.rb b/activemodel/lib/active_model/state_machine/event.rb
new file mode 100644
index 0000000000..cc7d563214
--- /dev/null
+++ b/activemodel/lib/active_model/state_machine/event.rb
@@ -0,0 +1,67 @@
+module ActiveModel
+ module StateMachine
+ class Event
+ attr_reader :name, :success
+
+ def initialize(name, options = {}, &block)
+ @name, @transitions = name, []
+ machine = options.delete(:machine)
+ if machine
+ machine.klass.send(:define_method, "#{name.to_s}!") do |*args|
+ machine.fire_event(name, self, true, *args)
+ end
+
+ machine.klass.send(:define_method, "#{name.to_s}") do |*args|
+ machine.fire_event(name, self, false, *args)
+ end
+ end
+ update(options, &block)
+ end
+
+ def fire(obj, to_state = nil, *args)
+ transitions = @transitions.select { |t| t.from == obj.current_state }
+ raise InvalidTransition if transitions.size == 0
+
+ next_state = nil
+ transitions.each do |transition|
+ next if to_state && !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.any? { |t| t.from? state }
+ end
+
+ def success?
+ !!@success
+ end
+
+ def ==(event)
+ if event.is_a? Symbol
+ name == event
+ else
+ name == event.name
+ end
+ end
+
+ def update(options = {}, &block)
+ if options.key?(:success) then @success = options[:success] end
+ if block then instance_eval(&block) end
+ self
+ end
+
+ private
+ def transitions(trans_opts)
+ Array(trans_opts[:from]).each do |s|
+ @transitions << StateTransition.new(trans_opts.merge({:from => s.to_sym}))
+ end
+ end
+ end
+ end
+end