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