lib/emittance/emitter.rb in emittance-0.0.1 vs lib/emittance/emitter.rb in emittance-0.0.2
- old
+ new
@@ -1,107 +1,131 @@
-##
-# An emitter is any object that has the power to emit an event. Extend this module in any class whose singleton or
-# instances you would like to have emit events.
-#
-# == Usage
-#
-# Whenever something warrants the emission of an event, you just need to call +#emit+ on that object. It is generally
-# a good practice for an object to emit its own events, but I'm not your mother so you can emit events from wherever
-# you want. It's probably not the best idea to do that, though. +#emit+ takes 2 params. First, it takes the identifier
-# for the event object type (which can also be the {Emittance::Event} class itself). See the "identifiers" section
-# of {Emittance::Event} for more info on this. The second argument is the payload. This is basically whatever you
-# want it to be, but you might want to standardize this on a per-event basis. The +Emittance+ will then (at this
-# time, synchronously) trigger each callback registered to listen for events of that identifier.
-#
-# +Emitter+ also provides a vanity class method that allows you to emit an event whenever a given method is called.
-# This event gets triggered whenever an instance of the class finishes executing a method. This event is emitted (and
-# therefore, all listening callbacks are triggered) between the point at which the method finishes executing and the
-# return value is passed to its invoker.
-#
-module Emittance::Emitter
- class << self
- # @private
- def extended(extender)
- Emittance::Emitter.emitter_eval(extender) do
- include ClassAndInstanceMethods
- extend ClassAndInstanceMethods
+# frozen_string_literal: true
+
+module Emittance
+ ##
+ # An emitter is any object that has the power to emit an event. Extend this module in any class whose singleton or
+ # instances you would like to have emit events.
+ #
+ # == Usage
+ #
+ # Whenever something warrants the emission of an event, you just need to call +#emit+ on that object. It is generally
+ # a good practice for an object to emit its own events, but I'm not your mother so you can emit events from wherever
+ # you want. It's probably not the best idea to do that, though. +#emit+ takes 2 params. First, it takes the identifier
+ # for the event object type (which can also be the {Emittance::Event} class itself). See the "identifiers" section
+ # of {Emittance::Event} for more info on this. The second argument is the payload. This is basically whatever you
+ # want it to be, but you might want to standardize this on a per-event basis. The +Emittance+ will then (at this
+ # time, synchronously) trigger each callback registered to listen for events of that identifier.
+ #
+ # +Emitter+ also provides a vanity class method that allows you to emit an event whenever a given method is called.
+ # This event gets triggered whenever an instance of the class finishes executing a method. This event is emitted (and
+ # therefore, all listening callbacks are triggered) between the point at which the method finishes executing and the
+ # return value is passed to its invoker.
+ #
+ module Emitter
+ # :nocov:
+ class << self
+ # @private
+ def extended(extender)
+ Emittance::Emitter.emitter_eval(extender) do
+ include ClassAndInstanceMethods
+ extend ClassAndInstanceMethods
+ end
end
- end
- # @private
- def non_emitting_method_for(method_name)
- "_non_emitting_#{method_name}".to_sym
- end
+ # @private
+ def non_emitting_method_for(method_name)
+ "_non_emitting_#{method_name}".to_sym
+ end
- # @private
- def emitting_method_event(emitter_klass, method_name)
- Emittance::Event.event_klass_for(emitter_klass)
- end
+ # @private
+ def emitting_method_event(emitter_klass, method_name)
+ Emittance::Event.event_klass_for(emitter_klass, method_name)
+ end
- # @private
- def emitter_eval(klass, *args, &blk)
- if klass.respond_to? :class_eval
- klass.class_eval *args, &blk
- else
- klass.singleton_class.class_eval *args, &blk
+ # @private
+ def emitter_eval(klass, *args, &blk)
+ if klass.respond_to? :class_eval
+ klass.class_eval *args, &blk
+ else
+ klass.singleton_class.class_eval *args, &blk
+ end
end
end
- end
+ # :nocov:
- # Included and extended whenever {Emittance::Emitter} is extended.
- module ClassAndInstanceMethods
- # Emits an {Emittance::Event event object} to watchers.
- #
- # @param identifier [Symbol, Emittance::Event] either an explicit Event object or the identifier that can be
- # parsed into an Event object.
- # @param payload [*] any additional information that might be helpful for an event's handler to have. Can be
- # standardized on a per-event basis by pre-defining the class associated with the
- def emit(identifier, payload)
- now = Time.now
- event_klass = _event_klass_for identifier
- event = event_klass.new(self, now, payload)
- _send_to_broker event
- end
+ # Included and extended whenever {Emittance::Emitter} is extended.
+ module ClassAndInstanceMethods
+ # Emits an {Emittance::Event event object} to watchers.
+ #
+ # @param identifier [Symbol, Emittance::Event] either an explicit Event object or the identifier that can be
+ # parsed into an Event object.
+ # @param payload [*] any additional information that might be helpful for an event's handler to have. Can be
+ # standardized on a per-event basis by pre-defining the class associated with the
+ #
+ # @return the payload
+ def emit(identifier, payload = nil, broker: :synchronous)
+ now = Time.now
+ event_klass = _event_klass_for identifier
+ event = event_klass.new(self, now, payload)
+ _send_to_broker event, broker
- private
+ payload
+ end
- # @private
- def _event_klass_for(*identifiers)
- Emittance::Event.event_klass_for *identifiers
- end
+ # If you don't know the specific identifier whose event you want to emit, you can send it a bunch of stuff and
+ # +Emitter+ will automatically generate an +Event+ class for you.
+ #
+ # @param identifiers [*] anything that can be used to generate an +Event+ class.
+ # @param payload (@see #emit)
+ def emit_with_dynamic_identifier(*identifiers, payload:, broker: :synchronous)
+ now = Time.now
+ event_klass = _event_klass_for *identifiers
+ event = event_klass.new(self, now, payload)
+ _send_to_broker event, broker
- # @private
- def _send_to_broker(event)
- Emittance::Broker.process_event event
- end
- end
+ payload
+ end
- # Tells the class to emit an event when a any of the given set of methods. By default, the event classes are named
- # accordingly: If a +Foo+ object +emits_on+ +:bar+, then the event's class will be named +FooBarEvent+, and will be
- # a subclass of +Emittance::Event+.
- #
- # The payload for this event will be the value returned from the method call.
- #
- # @param method_names [Symbol, String, Array<Symbol, String>] the methods whose calls emit an event
- def emits_on(*method_names)
- method_names.each do |method_name|
- non_emitting_method = Emittance::Emitter.non_emitting_method_for method_name
+ private
- Emittance::Emitter.emitter_eval(self) do
- if method_defined?(non_emitting_method)
- warn "Already emitting on #{method_name.inspect}"
- return
- end
+ # @private
+ def _event_klass_for(*identifiers)
+ Emittance::Event.event_klass_for *identifiers
+ end
- alias_method non_emitting_method, method_name
+ # @private
+ def _send_to_broker(event, broker)
+ Emittance::Brokerage.send_event event, broker
+ end
- module_eval <<-RUBY, __FILE__, __LINE__ + 1
- def #{method_name}(*args, &blk)
- return_value = #{non_emitting_method}(*args, &blk)
- emit self.class, return_value
- return_value
+ # Tells the class to emit an event when a any of the given set of methods. By default, the event classes are named
+ # accordingly: If a +Foo+ object +emits_on+ +:bar+, then the event's class will be named +FooBarEvent+, and will
+ # be a subclass of +Emittance::Event+.
+ #
+ # The payload for this event will be the value returned from the method call.
+ #
+ # @param method_names [Symbol, String, Array<Symbol, String>] the methods whose calls emit an event
+ def emits_on(*method_names)
+ method_names.each do |method_name|
+ non_emitting_method = Emittance::Emitter.non_emitting_method_for method_name
+
+ Emittance::Emitter.emitter_eval(self) do
+ if method_defined?(non_emitting_method)
+ warn "Already emitting on #{method_name.inspect}"
+ return
+ end
+
+ alias_method non_emitting_method, method_name
+
+ module_eval <<-RUBY, __FILE__, __LINE__ + 1
+ def #{method_name}(*args, &blk)
+ return_value = #{non_emitting_method}(*args, &blk)
+ emit_with_dynamic_identifier self.class, __method__, payload: return_value
+ return_value
+ end
+ RUBY
end
- RUBY
+ end
end
end
end
end