lib/stateful_enum/machine.rb in stateful_enum-0.5.0 vs lib/stateful_enum/machine.rb in stateful_enum-0.6.0

- old
+ new

@@ -1,11 +1,13 @@ # frozen_string_literal: true module StatefulEnum class Machine + attr_reader :events + def initialize(model, column, states, prefix, suffix, &block) - @model, @column, @states, @event_names = model, column, states, [] + @model, @column, @states, @events = model, column, states, [] @prefix = if prefix prefix == true ? "#{column}_" : "#{prefix}_" end @suffix = if suffix suffix == true ? "_#{column}" : "_#{suffix}" @@ -18,69 +20,70 @@ instance_eval(&block) if block end def event(name, &block) - raise ArgumentError, "event: :#{name} has already been defined." if @event_names.include? name - Event.new @model, @column, @states, @prefix, @suffix, name, &block - @event_names << name + raise ArgumentError, "event: :#{name} has already been defined." if @events.map(&:name).include? name + @events << Event.new(@model, @column, @states, @prefix, @suffix, name, &block) end class Event + attr_reader :name, :value_method_name + def initialize(model, column, states, prefix, suffix, name, &block) @states, @name, @transitions, @before, @after = states, name, {}, [], [] instance_eval(&block) if block transitions, before, after = @transitions, @before, @after - new_method_name = "#{prefix}#{name}#{suffix}" + @value_method_name = value_method_name = :"#{prefix}#{name}#{suffix}" # defining event methods model.class_eval do # def assign() - detect_enum_conflict! column, new_method_name + detect_enum_conflict! column, value_method_name # defining callbacks - define_callbacks new_method_name + define_callbacks value_method_name before.each do |before_callback| - model.set_callback new_method_name, :before, before_callback + model.set_callback value_method_name, :before, before_callback end after.each do |after_callback| - model.set_callback new_method_name, :after, after_callback + model.set_callback value_method_name, :after, after_callback end - define_method new_method_name do + define_method value_method_name do to, condition = transitions[send(column).to_sym] #TODO better error if to && (!condition || instance_exec(&condition)) #TODO transaction? - run_callbacks new_method_name do + run_callbacks value_method_name do original_method = self.class.send(:_enum_methods_module).instance_method "#{prefix}#{to}#{suffix}!" original_method.bind(self).call end else false end end # def assign!() - detect_enum_conflict! column, "#{new_method_name}!" - define_method "#{new_method_name}!" do - send(new_method_name) || raise('Invalid transition') + detect_enum_conflict! column, "#{value_method_name}!" + define_method "#{value_method_name}!" do + send(value_method_name) || raise('Invalid transition') end # def can_assign?() - detect_enum_conflict! column, "can_#{new_method_name}?" - define_method "can_#{new_method_name}?" do + detect_enum_conflict! column, "can_#{value_method_name}?" + define_method "can_#{value_method_name}?" do state = send(column).to_sym return false unless transitions.key? state _to, condition = transitions[state] !condition || instance_exec(&condition) end # def assign_transition() - detect_enum_conflict! column, "#{new_method_name}_transition" - define_method "#{new_method_name}_transition" do + detect_enum_conflict! column, "#{value_method_name}_transition" + define_method "#{value_method_name}_transition" do transitions[send(column).to_sym].try! :first end end end