One of the really nice things about Ruby is its ability to change the behaviour of its classes. So it is easy to add new behaviours, as needed to a class.
The Object class has a method, methods, which allows you to see the objects associated with a particular object.
1 2 3 |
>> "methods".methods => ["chop!", "concat", "upcase!", "collect", "pretty_print_cycle", "sort", "member?", "methods", "chop", "replace", "gem", "include?", "each_with_index", "taint", "instance_variable_defined?", "empty?", "crypt", "chomp!", "downcase!", "map", "match", "slice!", "pretty_print", "__id__", "sort_by", "singleton_methods", "chomp", "tr!", "my_methods", "zip", "respond_to?", "to_str", "dclone", "po", "nil?", "intern", "strip!", "capitalize!", "inject", "succ", "__send__", "__clone__", "protected_methods", "grep", "tainted?", "strip", "tr_s!", "each", "dump", "untaint", "instance_of?", "pretty_print_instance_variables", "scan", "lstrip!", "equal?", "swapcase!", "partition", "hex", "private_methods", "hash", "find", "lstrip", "delete!", "send", "upcase", "require", "kind_of?", "succ!", "poc", "freeze", "rstrip!", "eql?", "pretty_inspect", "ljust", "method", "next", "tr", "id", "oct", "detect", "public_methods", "casecmp", "squeeze!", "instance_eval", "unpack", "rstrip", "%", "downcase", "is_a?", "each_line", "all?", "rjust", "object_id", "type", "*", "tr_s", "split", "+", "find_all", "instance_variables", "insert", "frozen?", "capitalize", "any?", "ri", "to_a", "next!", "pretty_print_inspect", "each_byte", "center", "min", "upto", "class", "delete", "to_sym", "reverse", "build_hash", "sub!", "<=>", "instance_variable_get", "length", "select", "==", "between?", "===", "to_i", "swapcase", "to_s", "extend", "display", "sum", "sub", ">=", "max", "<=", "index", "squeeze", "clone", "gsub!", "=~", "instance_variable_set", "size", "<", "what?", "reject", ">", "to_f", "entries", "slice", "inspect", "[]", "gsub", "rindex", "reverse!", "[]=", "count", "dup", "<<"] |
Object class has methods:
1 2 3 |
>> Object.new.methods => ["inspect", "clone", "pretty_print_cycle", "method", "__clone__", "public_methods", "pretty_print_inspect", "instance_variable_defined?", "equal?", "freeze", "poc", "methods", "respond_to?", "pretty_inspect", "pretty_print", "dup", "instance_variables", "__id__", "eql?", "object_id", "require", "what?", "id", "singleton_methods", "send", "pretty_print_instance_variables", "taint", "frozen?", "instance_variable_get", "__send__", "instance_of?", "to_a", "gem", "ri", "type", "protected_methods", "instance_eval", "==", "display", "===", "instance_variable_set", "po", "my_methods", "kind_of?", "extend", "to_s", "class", "hash", "dclone", "private_methods", "=~", "tainted?", "untaint", "nil?", "is_a?"] |
Object can be interesting. But the methods method returns an array, and in Ruby, when you subtract one array from another, you subtract the intersection between the first and second array:
1 2 3 |
>> "methods".methods - Object.new.methods => ["chop!", "concat", "upcase!", "collect", "sort", "member?", "chop", "replace", "include?", "each_with_index", "empty?", "crypt", "chomp!", "downcase!", "map", "match", "slice!", "sort_by", "chomp", "tr!", "zip", "to_str", "intern", "strip!", "capitalize!", "inject", "succ", "grep", "strip", "tr_s!", "each", "dump", "scan", "lstrip!", "swapcase!", "partition", "hex", "find", "lstrip", "delete!", "upcase", "succ!", "rstrip!", "ljust", "next", "tr", "oct", "detect", "casecmp", "squeeze!", "unpack", "rstrip", "%", "downcase", "each_line", "all?", "rjust", "*", "tr_s", "split", "+", "find_all", "insert", "capitalize", "any?", "next!", "each_byte", "center", "min", "upto", "delete", "to_sym", "reverse", "build_hash", "sub!", "<=>", "length", "select", "between?", "to_i", "swapcase", "sum", "sub", ">=", "max", "<=", "index", "squeeze", "gsub!", "size", "<", "reject", ">", "to_f", "entries", "slice", "[]", "gsub", "rindex", "reverse!", "[]=", "count", "<<"] |
Object we can ensure that our method is available for any object created:
1 2 3 4 5 6 |
class Object def my_methods self.methods - Object.methods end end |
1 2 3 |
>> "methods".my_methods => ["chop!", "concat", "upcase!", "collect", "sort", "member?", "chop", "replace", "each_with_index", "empty?", "crypt", "chomp!", "downcase!", "map", "match", "slice!", "sort_by", "chomp", "tr!", "zip", "to_str", "intern", "strip!", "capitalize!", "inject", "succ", "grep", "strip", "tr_s!", "each", "dump", "scan", "lstrip!", "swapcase!", "partition", "hex", "find", "lstrip", "delete!", "upcase", "succ!", "rstrip!", "ljust", "next", "tr", "oct", "detect", "casecmp", "squeeze!", "unpack", "rstrip", "%", "downcase", "each_line", "all?", "rjust", "*", "tr_s", "split", "+", "find_all", "insert", "capitalize", "any?", "next!", "each_byte", "center", "min", "upto", "delete", "to_sym", "reverse", "build_hash", "sub!", "length", "select", "between?", "to_i", "swapcase", "sum", "sub", "max", "index", "squeeze", "gsub!", "size", "reject", "to_f", "entries", "slice", "[]", "gsub", "rindex", "reverse!", "[]=", "count", "<<"] |
Object. So, we can add our method definition to the .irbrc, where it will be picked up any time we have an interactive ruby session.
Update:
Joe O'Brien of Edgecase suggested adding a sort to the self.methods to make the output sorted.
