aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel/lib/active_model/state_machine/event.rb
diff options
context:
space:
mode:
authorrick <technoweenie@gmail.com>2008-06-28 09:19:44 -0700
committerrick <technoweenie@gmail.com>2008-06-28 09:19:44 -0700
commit74cb05698684f237a7eb91afadec0020d8910c70 (patch)
treeff961d9f9c2119a6608db90bc41d713a191a9b9f /activemodel/lib/active_model/state_machine/event.rb
parentb9528ad3c5379896b00772cb44faf1db0fd882d7 (diff)
downloadrails-74cb05698684f237a7eb91afadec0020d8910c70.tar.gz
rails-74cb05698684f237a7eb91afadec0020d8910c70.tar.bz2
rails-74cb05698684f237a7eb91afadec0020d8910c70.zip
add basic events and transitions. still more tests to convert
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