module UltraMarathon::Callbacks::ClassMethods

Public Instance Methods

callbacks(*callback_names) click to toggle source

Add one or more new callbacks for class E.g.

callbacks :after_save

Defines a class method `after_save` which takes an object responding to :call (Proc or lambda) or a symbol to be called in the context of the instance

Also defines `invoke_after_save_callbacks` instance method for designating when the callbacks should be invoked

# File lib/ultra_marathon/callbacks.rb, line 42
def callbacks(*callback_names)
  new_callbacks = Set.new(callback_names) - _callback_names
  new_callbacks.each do |callback_name|
    add_callbacks_accessor callback_name
    define_callback callback_name
    add_invoke_callback callback_name
  end
  self._callback_names = new_callbacks
end

Private Instance Methods

_callback_names() click to toggle source
# File lib/ultra_marathon/callbacks.rb, line 61
def _callback_names
  @_callback_names ||= Set.new
end
_callback_names=(new_callbacks) click to toggle source

Only keep unique callback names

# File lib/ultra_marathon/callbacks.rb, line 57
def _callback_names=(new_callbacks)
  @_callback_names = _callback_names | new_callbacks
end
add_callback_array_writer(callback_name) click to toggle source

Use protected since this is used by parent classes to inherit callbacks

# File lib/ultra_marathon/callbacks.rb, line 118
def add_callback_array_writer(callback_name)
  attr_writer "#{callback_name}_callbacks"
  protected "#{callback_name}_callbacks="
end
add_callback_setter(callback_name) click to toggle source
# File lib/ultra_marathon/callbacks.rb, line 101
def add_callback_setter(callback_name)
  define_singleton_method(callback_name) do |callback, options={}|
    if valid_callback? callback
      send("#{callback_name}_callbacks") << [callback, options]
    else
      raise ArgumentError.new("Expected callable object or symbol, got #{callback.class}")
    end
  end
end
add_callbacks_accessor(callback_name) click to toggle source

Defines class level accessor that memoizes the set of callbacks @param callback_name [String, Symbol] @example

add_callbacks_accessor(:after_save)

# Equivalent to
#
# def self.after_save_callbacks
#   @after_save_callbacks ||= []
# end
# File lib/ultra_marathon/callbacks.rb, line 86
def add_callbacks_accessor(callback_name)
  accessor_name = "#{callback_name}_callbacks"
  instance_variable_name = :"@#{accessor_name}"
  define_singleton_method("#{callback_name}_callbacks") do
    instance_variable_get(instance_variable_name) ||
    instance_variable_set(instance_variable_name, [])
  end
end
add_invoke_callback(callback_name) click to toggle source
# File lib/ultra_marathon/callbacks.rb, line 130
def add_invoke_callback(callback_name)
  define_method("invoke_#{callback_name}_callbacks") do |*args|
    callbacks = self.class.send :"#{callback_name}_callbacks"
    callbacks.each do |callback, options|
      next unless callback_conditions_met?(options)
      contexticute(callback, args, options[:context] || self)
    end
  end
end
clear_callbacks!() click to toggle source

Clears all callbacks. Useful for testing and inherited classes

# File lib/ultra_marathon/callbacks.rb, line 124
def clear_callbacks!
  _callback_names.each do |callback_name|
    instance_variable_set(:"@#{callback_name}_callbacks", nil)
  end
end
define_callback(callback_name) click to toggle source

Validates that the callback is valid and adds it to the callback array

# File lib/ultra_marathon/callbacks.rb, line 96
def define_callback(callback_name)
  add_callback_setter(callback_name)
  add_callback_array_writer(callback_name)
end
inherited(base) click to toggle source

On inheritance, the child should inheirit all callbacks of the parent. We don't use class variables because we don't want sibling classes to share callbacks

# File lib/ultra_marathon/callbacks.rb, line 68
def inherited(base)
  base.send(:callbacks, *_callback_names)
  _callback_names.each do |callback_name|
    parent_callbacks = send(:"#{callback_name}_callbacks").dup
    base.instance_variable_set(:"@#{callback_name}_callbacks", parent_callbacks)
  end
end
valid_callback?(callback) click to toggle source

Callbacks should either be callable (Procs, lambdas) or a symbol

# File lib/ultra_marathon/callbacks.rb, line 112
def valid_callback?(callback)
  callback.respond_to?(:call) || callback.is_a?(Symbol)
end