lib/finite_machine/observer.rb in finite_machine-0.2.0 vs lib/finite_machine/observer.rb in finite_machine-0.3.0
- old
+ new
@@ -26,11 +26,11 @@
# @api private
def call(&block)
instance_eval(&block)
end
- # Register callback for a given event.
+ # Register callback for a given event
#
# @param [Symbol] event_type
# @param [Symbol] name
# @param [Proc] callback
#
@@ -40,10 +40,21 @@
ensure_valid_callback_name!(name)
hooks.register event_type, name, callback
end
end
+ # Unregister callback for a given event
+ #
+ # @api public
+ def off(event_type = ANY_EVENT, name = ANY_STATE, &callback)
+ sync_exclusive do
+ hooks.unregister event_type, name, callback
+ end
+ end
+
+ module Once; end
+
def listen_on(type, *args, &callback)
name = args.first
events = []
if machine.states.include?(name) || name == ANY_STATE_HOOK
events << :"#{type}state"
@@ -65,24 +76,22 @@
def on_exit(*args, &callback)
listen_on :exit, *args, &callback
end
- def method_missing(method_name, *args, &block)
- _, event_name, callback_name = *method_name.to_s.match(/^(on_\w+?)_(\w+)$/)
- if callback_names.include?(callback_name.to_sym)
- send(event_name, callback_name.to_sym, *args, &block)
- else
- super
- end
+ def once_on_enter(*args, &callback)
+ listen_on :enter, *args, &callback.extend(Once)
end
- def respond_to_missing?(method_name, include_private = false)
- _, callback_name = *method_name.to_s.match(/^(on_\w+?)_(\w+)$/)
- callback_names.include?(callback_name.to_sym)
+ def once_on_transition(*args, &callback)
+ listen_on :transition, *args, &callback.extend(Once)
end
+ def once_on_exit(*args, &callback)
+ listen_on :exit, *args, &callback.extend(Once)
+ end
+
TransitionEvent = Struct.new(:from, :to, :name) do
def build(_transition)
self.from = _transition.from_state
self.to = _transition.to
self.name = _transition.name
@@ -104,10 +113,11 @@
[event.type, ANY_EVENT].each do |event_type|
[event.state, ANY_STATE,
ANY_STATE_HOOK, ANY_EVENT_HOOK].each do |event_state|
hooks.call(event_type, event_state, event) do |hook|
run_callback(hook, event)
+ off(event_type, event_state, &hook) if hook.is_a?(Once)
end
end
end
end
end
@@ -127,9 +137,41 @@
exception = InvalidCallbackNameError
machine.catch_error(exception) ||
raise(InvalidCallbackNameError, "#{name} is not a valid callback name." +
" Valid callback names are #{callback_names.to_a.inspect}")
end
+ end
+
+ # Forward the message to observer
+ #
+ # @param [String] method_name
+ #
+ # @param [Array] args
+ #
+ # @return [self]
+ #
+ # @api private
+ def method_missing(method_name, *args, &block)
+ _, event_name, callback_name = *method_name.to_s.match(/^(\w*?on_\w+?)_(\w+)$/)
+ if callback_names.include?(callback_name.to_sym)
+ public_send(event_name, :"#{callback_name}", *args, &block)
+ else
+ super
+ end
+ end
+
+ # Test if a message can be handled by observer
+ #
+ # @param [String] method_name
+ #
+ # @param [Boolean] include_private
+ #
+ # @return [Boolean]
+ #
+ # @api private
+ def respond_to_missing?(method_name, include_private = false)
+ *_, callback_name = *method_name.to_s.match(/^(\w*?on_\w+?)_(\w+)$/)
+ callback_names.include?(:"#{callback_name}")
end
end # Observer
end # FiniteMachine