Code
First create a module containing a single module method, setup. This module could be put in a file that is required as needed. This module method will be invoked from a module containing instance methods to be included in a given class. Using aliases, it modifies those instance methods to print a message (containing the method name) before executing the remainder of its code.
Module AddMessage
module AddMessage
def self.setup(mod, msg_pre, msg_post)
mod.instance_methods(false).
each do |m|
am = "_#{m}".to_sym
mod.send(:alias_method, am, m)
mod.send(:private, am)
mod.send(:define_method, m) do |*args, &block|
puts "%s %s %s" % [msg_pre, m, msg_post]
send(am, *args, &block)
end
end
end
end
Module to be included in class
module LegacyStuff
def old1
"hi"
end
def old2(a, b)
yield(a, b)
end
AddMessage.setup(self, "Warning:", "is deprecated")
end
AddMessage::setup is passed three arguments, the name of the calling module and a message prefix and message suffix that are used to form the warning message. When an instance method m in this module is executed by a class instance the message "Warning: #{m} is deprecated" is printed (e.g., "Warning: old1 is deprecated") before the remaining calculations are performed.
Use
LegacyStuff is simply included by a class.
class C
include LegacyStuff
# <constants, methods and so forth go here>
end
c = C.new
c.old1
# Warning: old1 is deprecated
#=> "hi"
c.old2(1,2) { |a,b| a+b }
# Warning: old2 is deprecated
#=> 3
c.cat
#=> NoMethodError: undefined method `cat' for #<C:0x000000008ef0a8>
Explanation of the module method AddMessage:setup
The following (of the generally less-familiar) methods are used by this method: Module#instance_methods, Module#alias_method, Module#private and Module#define_method.
The following three steps are performed for each instance method m defined in module mod (e.g., elements of the array LegacyStuff.instance_methods(false)).
mod.send(:alias_method, am, m)
Create an alias am of the method (e.g., _:old1 for old1).
mod.send(:private, am)
Make the alias am a private method (e.g., _old1).
mod.send(:define_method, m) do |*args, &block| ... end
Redefine the method m (e.g., old1) to print the indicate string and then execute the alias am (e.g., _old1).