Module: Stenotype::Emitter

Defined in:
lib/stenotype/emitter.rb

Overview

An extension for a plain Ruby class in order to track invocation of instance methods.

Constant Summary collapse

ClassMethodsExtension =

Class methods for target to be extended by

Class.new(Module)
InstanceMethodsExtension =

Instance methods to be included into target class ancestors chain

Class.new(Module)

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.build_class_methods(class_mod) ⇒ Object

Adds class method [#emit_klass_event_before] to every class inherited from [Object]



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/stenotype/emitter.rb', line 114

def self.build_class_methods(class_mod)
  class_mod.module_eval <<-RUBY, __FILE__, __LINE__ + 1
    def emit_event_before(*methods)
      proxy = const_get(:InstanceProxy)

      methods.each do |method|
        proxy.module_eval do
          define_method(method) do |*args, **rest_args, &block|
            Stenotype::Event.emit!(
              # @todo How do we name such events?
              "instance_method",
              {
                type: "instance_method",
                class: self.class.name,
                method: __method__,
              },
              eval_context: { klass: self },
            )
            super(*args, **rest_args, &block)
          end
        end
      end

      send(:prepend, proxy)
    end

    def emit_klass_event_before(*class_methods)
      proxy = const_get(:ClassProxy)

      class_methods.each do |method|
        proxy.module_eval do
          define_method(method) do |*args, **rest_args, &block|
            Stenotype::Event.emit!(
              # @todo How do we name such events?
              "class_method",
              {
                type: "class_method",
                class: self.name,
                method: __method__,
              },
              eval_context: { klass: self },
            )
            super(*args, **rest_args, &block)
          end
        end

        singleton_class.send(:prepend, proxy)
      end
    end
  RUBY
end

.build_instance_methods(instance_mod) ⇒ Object

Adds an instance method: [#emit_event] to a target class where Stenotype::Emitter in included in



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/stenotype/emitter.rb', line 93

def self.build_instance_methods(instance_mod)
  instance_mod.module_eval <<-RUBY, __FILE__, __LINE__ + 1
    def emit_event(event_name, attributes = {}, method: caller_locations.first.label, eval_context: nil)
      Stenotype::Event.emit!(
        event_name,
        {
          type: "instance_method",
          class: self.class.name,
          method: method.to_sym,
          **attributes,
        },
        eval_context: (eval_context || { klass: self })
      )
    end
  RUBY
end

.emit_event_before(*methods) ⇒ Object

A class method injected into target class to track instance methods invocation

Examples:

Usage of emit_event_before

class SomeRubyClass
  include Stenotype::Emitter
  emit_event_before :some_method # Triggers an event upon calling some_method

  def some_method
    # do something
  end
end

Parameters:

  • methods (Array<Symbol>)

    A list of method before which an event will be emitted



# File 'lib/stenotype/emitter.rb', line 56

.emit_klass_event_before(*class_methods) ⇒ Object

A class method injected into a target class to track class methods invocation

Examples:

Usage emit_klass_event_before

class SomeRubyClass
  include Stenotype::Emitter
  emit_klass_event_before :some_method # Triggers an event upon calling some_method

  def self.some_method
    # do something
  end
end

Parameters:

  • class_methods (Array<Symbol>)

    A list of class method before which an event will be emitted



# File 'lib/stenotype/emitter.rb', line 72

Instance Method Details

#emit_event(name, attributes = {}, method: caller_locations.first.label, eval_context: nil) ⇒ Stenotype::Event

A method injected into target class to manually track events

Examples:

Usage of emit_event

class SomeRubyClass
  include Stenotype::Emitter

  def some_method
    data = collection_data
    emit_event(data, eval_context: self) # Track event with given data
    data
  end
end

Parameters:

  • name ([String, Symbol])

    Event name.

  • attributes (Hash) (defaults to: {})

    Data to be sent to the targets.

  • method (String) (defaults to: caller_locations.first.label)

    An optional method name.

  • eval_context (Hash) (defaults to: nil)

    A hash linking object to context handler

Returns:



# File 'lib/stenotype/emitter.rb', line 35