Metaprogramming from RubyMonk
First off, what is metaprogramming? It essentially is writing code that uses code rather than actual data, modifying the program as it runs. Better still, it's not just useful in Ruby, it can be used in Lisp, Java, and C# under various names.
Common Metaprogramming methods
#send: I was completely misinformed previously. Apparently, this command can take the method name as both a symbol and and string!
#method_missing: The method that is called when there is no method for a specific object. This method can accept multiple arguments (collect them all using the splat operator!) as well as a proc block.
#define_method("method_name") { |expected_argument| code! }: Will create a method with the method name and expected arguments. When making methods from words that might have spaces in them, use gsub (words.gsub('_', ' '))
#method(method_name) will pull up a method as an object. As with send, you can pass in the method name as a string or a symbol. You can then call #arity or #parameters on the method object. #arity will return the number of arguments allowed (an optional argument makes the number negative. If there are more than one optional argument, only the first is counted). #parameters returns of the arguments. Arguments are represented by arrays that say whether the argument is required (:req), optional (:opt), optional splat (:rest), or a code block (:block), as well as the name for the argument. These method objects are similar to proc objects, but are bound to themselves and only accessible to variables and objects within their scope. The #receiver and #owner methods will return the object or class that can receive the method (respectively).
#methods or #public_methods will return the list of public methods for the object and its ancestors (classes it inherits from). #public_methods(false) will return only the methods for the object's immediate class, and not it's ancestors. This can be useful for weeding out the many methods automatically inherited by all Ruby objects.
Class::const_get(constant_name): returns value for a constant within the specified class. The method will even find constants that are defined in classes inherited by the specifed class. This can be used to instantiate classes if you pass in the class name as the constant name.
#instance_variable_get("@var"): will retrieve the value of an instance variable without a getter method.
def inspect_instance_variable(class_name, variable) Module.const_get(class_name).new.instance_variable_get("@#{variable}") end
example of how to use #const_get in combination with #instance_variable_get to return the value of a specific variable
Reference
RubyMonk: A bit confusing at times (trying to figure out what to do in example code was almost as challenging as the material itself, especially when there was a syntax error an meaningless number lines), but provided an adequate introduction to metapgramming. Have to say, the AppAcademy curriculum is clearer. However, Last Airbender references make up for it!
So pretty! Only thing is, why couldn't the instruction be easier to understand?










