module NoBacksies
NoBacksies
module ecapsulates all supported callback mixins.
NoBacksies::Callbacks
can be mixed-in and all supported callbacks will be applied to the class or module.
class Y include NoBacksies::Callbacks def self.list @list ||= [] end callback :method_added do |method| list << method end def foo; end def bar; end end Y.list.assert #=> [:foo, :bar]
Using callbacks can easily lead to infinite loops. NoBacksies
makes it easier to control callback expression via the callback_express method.
class Z include NoBacksies::Callbacks def self.list @list ||= [] end callback :method_added do |method| callback_express :method_added=>false do define_method("#{method}!") do send(method) + "!" end end end def foo; "foo"; end def bar; "bar"; end end y = Y.new y.foo! #=> "foo!"
Calling Super¶ ↑
Each callback invocation passes along a superblock procedure, which can be used to invoke ‘super` for the underlying callback method. For example, it is common to call `super` in a `const_missing` callback if the dynamic constant lookup fails.
callback :const_missing do |const, &superblock| psuedo_constants[const] || superblock.call end
By default, super is called after call callback procedures are called becuase that is by far the most commonly desired behavior. To suppress this behavior pass the ‘:superless=>true` flag to the `callback` method.
callback :included, :superless=>true do |mod| ... end
Customizing the Underlying Callback Procedure¶ ↑
Every callback follows the same simply pattern, e.g. for ‘method_added`:
def self.method_added(method) if defined?(super) callback_invoke(:method_added, method){ super(method) } else callback_invoke(:method_added, method) end end
So it is easy enough to customize if you have some special requirements. Say you want to call super before all callback procedures, and never allow any callback procedure to do so themselves, then you could simply redefine the underlying callback method as:
def self.method_added(method) super(method) if defined?(super) callback_invoke(:method_added, method) end
NOTE: Currently the NoBacksies
module only supports class level callbacks. We will look into adding instance level callbacks, such as ‘method_missing` in a future version.