Basic Example
First require the NoBacksies library.
require 'no_backsies'
Include the Callbacks module in a class and define a callback procedure.
class Y
include NoBacksies::Callbacks
def self.list
@list ||= []
end
callback :method_added do |method|
list << method
end
def foo; end
def ; end
end
We can see that list
holds the methods added.
Y.list.assert == [:foo, :bar]
Callback Expression
NoBacksies makes it easier to control callback expression. This is useful in the prevention of infinite recursion. For instance, infinite recursion is a common problem when a method_added
callback defines a new method.
Here is an example that demonstrates how to work around this problem using the callback_express
method.
class Z
include NoBacksies::Callbacks
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"; end
end
In this example, a new ‘Z` object will get an automatically defined bang method for every explicitly defined method.
z = Z.new
z.foo #=> "foo"
z.foo! #=> "foo!"
z. #=> "bar"
z. #=> "bar!"
Callback Options
Once Callback Option
NoBacksies supports special callback options. The first is :once
. By setting :once
to true
, the callback will be used one time and then removed.
class Q
include NoBacksies::Callbacks
def self.list
@list ||= []
end
callback :method_added, :once=>true do |method|
list << method
end
def foo; "foo"; end
def ; "bar"; end
end
Here we see that only :foo has been added to the list.
Q.list #=> [:foo]
Safe Callback Option
The other option supported is :safe
. When :safe
is set to true the callback is automatically wrapped in an #callback_express block that sets the expression of the callback to false while it is being processed. This means we can rewrite our first example more succinctly.
class Z2
include NoBacksies::Callbacks
callback :method_added, :safe=>true do |method|
define_method("#{method}!") do
send(method) + "!"
end
end
def foo; "foo"; end
def ; "bar"; end
end
In this example, a new ‘Z` object will get an automatically defined bang method for every explicitly defined method.
z = Z2.new
z.foo #=> "foo"
z.foo! #=> "foo!"
z. #=> "bar"
z. #=> "bar!"
Method Added
Given a class that defines a no-backsies method_added
callback.
class Y
include NoBacksies::Callbacks
def self.list
@list ||= []
end
callback :method_added do |method|
list << method
end
def foo; end
def ; end
end
Then the results are as follows.
Y.list #=> [:foo, :bar]
Method Removed
Given a class that defines a no-backsies method_removed
callback.
class Y
include NoBacksies::Callbacks
def self.list
@list ||= []
end
callback :method_removed do |method|
list << method
end
def foo; end
def ; end
remove_method(:foo)
remove_method(:bar)
end
Then the results are as follows.
Y.list #=> [:foo, :bar]
Method Undefined
Given a class that defines a no-backsies method_undefined
callback.
class Y
include NoBacksies::Callbacks
def self.list
@list ||= []
end
callback :method_undefined do |method|
list << method
end
def foo; end
def ; end
undef_method(:foo)
undef_method(:bar)
end
Then the results are as follows.
Y.list #=> [:foo, :bar]
Singleton Method Added
Given a class that defines a no-backsies singleton_method_added
callback.
class Y
include NoBacksies::Callbacks
def self.list
@list ||= []
end
callback :singleton_method_added do |method|
list << method
end
def self.foo; end
def self.; end
end
Then the results are as follows.
Y.list #=> [:foo, :bar]
Singleton Method Removed
Given a class that defines a no-backsies singleton_method_removed
callback.
class Y
include NoBacksies::Callbacks
def self.list
@list ||= []
end
callback :singleton_method_removed do |method|
list << method
end
def self.foo; end
def self.; end
class << self
remove_method(:foo)
remove_method(:bar)
end
end
Then the results are as follows.
Y.list #=> [:foo, :bar]
Singleton Method Undefined
class Y
include NoBacksies::Callbacks
def self.list
@list ||= []
end
callback :singleton_method_undefined do |method|
list << method
end
def self.foo; end
def self.; end
class << self
undef_method(:foo)
undef_method(:bar)
end
end
Y.list #=> [:foo, :bar]
Constant Missing
Given a class that defines a no-backsies const_missing
callback.
class Y
include NoBacksies::Callbacks
def self.list
@list ||= []
end
callback :const_missing, :superless=>true do |const|
list << const
end
FOO
BAR
end
Then the results are as follows.
Y.list #=> [:FOO, :BAR]
Notice we used ‘:superless` to prevent super from being called, which would have raised an NameError.
Included
Given a class that defines a no-backsies included
callback.
module U
include NoBacksies::Callbacks
def self.list
@list ||= []
end
callback :included do |mod|
list << mod
end
end
class X
include U
end
class Y
include U
end
Then the results are as follows.
U.list #=> [X, Y]
Extended
Given a class that defines a no-backsies extended
callback.
module U
include NoBacksies::Callbacks
def self.list
@list ||= []
end
callback :extended do |mod|
list << mod
end
end
class X
extend U
end
class Y
extend U
end
Then the results are as follows.
U.list #=> [X, Y]
Inherited
Given a class that defines a no-backsies inherited
callback.
class Y
include NoBacksies::Callbacks
def self.list
@list ||= []
end
callback :inherited do |base|
list << base
end
end
z = Class.new(Y)
Then the results are as follows.
Y.list #=> [z]