lib/stateful_enum/machine.rb in stateful_enum-0.1.0 vs lib/stateful_enum/machine.rb in stateful_enum-0.2.0
- old
+ new
@@ -25,15 +25,21 @@
define_transition_methods
end
def define_transition_methods
- column, name, transitions = @column, @name, @transitions
+ column, name, transitions, before, after = @column, @name, @transitions, @before, @after
@model.send(:define_method, name) do
- if (to = transitions[self.send(column).to_sym])
- self.class.instance_variable_get(:@_enum_methods_module).instance_method("#{to}!").bind(self).call
+ to, condition = transitions[self.send(column).to_sym]
+ #TODO better error
+ if to && (!condition || instance_exec(&condition))
+ #TODO transaction?
+ instance_eval(&before) if before
+ ret = self.class.instance_variable_get(:@_enum_methods_module).instance_method("#{to}!").bind(self).call
+ instance_eval(&after) if after
+ ret
else
false
end
end
@@ -44,21 +50,40 @@
@model.send(:define_method, "can_#{name}?") do
transitions.has_key? self.send(column).to_sym
end
@model.send(:define_method, "#{name}_transition") do
- transitions[self.send(column).to_sym]
+ transitions[self.send(column).to_sym].try! :first
end
end
- def transition(transitions)
+ def transition(transitions, options = {})
+ if options.blank?
+ options[:if] = transitions.delete :if
+ #TODO should err if if & unless were specified together?
+ if (unless_condition = transitions.delete :unless)
+ options[:if] = -> { !instance_exec(&unless_condition) }
+ end
+ end
transitions.each_pair do |from, to|
raise "Undefined state #{to}" unless @states.has_key? to
Array(from).each do |f|
raise "Undefined state #{f}" unless @states.has_key? f
- @transitions[f] = to
+ @transitions[f] = [to, options[:if]]
end
end
+ end
+
+ def all
+ @states.keys
+ end
+
+ def before(&block)
+ @before = block
+ end
+
+ def after(&block)
+ @after = block
end
end
end
end