
Before you begin, you need to install the JDK and NetBeans IDE
software on your
computer as
described in
here.
Learning points
Tasks to be performed

| # Introspection example puts "----Display all the methods of Object class" puts Object.methods.sort puts "----Check if Object class has name method" puts Object.respond_to?(:name) #=> true puts "----Check if Object class has send method" puts Object.respond_to?(:send) #=> true puts "----Check if Object class has does_not_exist method" puts Object.respond_to?(:does_not_exist) #=> false |


| ----Display all the methods of
Object Display all the methods of Object < <= <=> == === =~ > >= __id__ __send__ allocate ancestors autoload autoload? class class_eval class_variable_defined? class_variables clone const_defined? const_get const_missing const_set constants display dup eql? equal? extend extended freeze frozen? hash id include? included included_modules inherited initialize_copy inspect instance_eval instance_exec instance_method instance_methods instance_of? instance_variable_defined? instance_variable_get instance_variable_set instance_variables is_a? kind_of? method method_defined? methods module_eval name new nil? object_id private_class_method private_instance_methods private_method_defined? private_methods protected_instance_methods protected_method_defined? protected_methods public_class_method public_instance_methods public_method_defined? public_methods respond_to? send singleton_methods superclass taint tainted? to_a to_s type untaint ----Check if Object class has name method true ----Check if Object class has send method true ----Check if Object class has does_not_exist method false |
| # Introspection example puts "----Define Hello class" class Hello def myhellomethod(name) end end puts "----Check if Hello object has a method called myhellomethod" hello_instance = Hello.new puts hello_instance.respond_to?(:myhellomethod) puts "----Check if Hello object has a method called xyz" puts hello_instance.respond_to?(:xyz) |
| ----Define Hello class ----Check if Hello object has a method called myhellomethod true ----Check if Hello object has a method called xyz false |
| class A end class B < A end a = A.new b = B.new puts "----Exercise instance_of? and kind_of? methods among object instances" puts a.instance_of?(A) puts b.instance_of?(A) puts b.kind_of?(A) puts "----Exercise instance_of? and kind_of? methods for a class" puts A.instance_of?(Class) puts A.kind_of?(Class) puts "----Display class information" puts a.class puts a.class.class |
| ----Exercise instance_of? and
kind_of? methods among object instances true false true ----Exercise instance_of? and kind_of? methods for a class true true ----Display class information A Class |
| some_string = 'http://google.com' puts "----Print the object's class, methods, superclass and ancestors (mixins and superclasses)" p some_string.class p some_string.methods p some_string.class.superclass p some_string.class.ancestors puts "----Print the methods of the String class" p String.private_instance_methods(false) p String.public_instance_methods(false) puts "----Pass true to recurse into parent classes" p String.public_instance_methods(true) puts "----Call instance methods with send()" "Random text".send(:length) # 11 -23.send(:succ) # 22 puts "----Use Method objects and call()" length_method = "Random text".method(:length) length_method.call # 11 puts "----Another way, using eval()" length_method = %q{"Random text".length} eval length_method |
| ----Print the object's class,
methods, superclass and ancestors (mixins and superclasses) String ["upcase!", "to_str", "lstrip", "upto", "sum", "crypt", "scan", "reverse!", "==", "each_byte", "=~", "tr!", "squeeze!", "inspect", "chop", "next!", "rstrip", "casecmp", "split", "succ!", "to_f", "<", "[]=", "~", "center", "slice!", "slice", "reverse", "sub", "insert", "upcase", "tr_s!", ">", "next", "strip!", "squeeze", "dump", "count", "sub!", "hash", "lstrip!", "to_sym", "replace", "<=", "hex", "strip", "capitalize!", "length", "chop!", "each_line", "swapcase", "[]", "include?", "chomp!", "<<", "gsub", "intern", "succ", "capitalize", "oct", "+", "delete!", "initialize_copy", "rindex", "chomp", "<=>", "to_i", "eql?", "tr_s", "match", "unpack", "index", "rstrip!", "*", "delete", "gsub!", "to_s", "rjust", "%", ">=", "empty?", "size", "swapcase!", "concat", "tr", "ljust", "each", "downcase!", "downcase", "zip", "sort", "reject", "to_a", "find", "entries", "map", "max", "min", "each_with_index", "member?", "inject", "sort_by", "collect", "partition", "detect", "all?", "select", "grep", "find_all", "any?", "between?", "methods", "freeze", "extend", "object_id", "nil?", "method", "tainted?", "is_a?", "instance_variable_get", "instance_variable_defined?", "instance_variable_set", "display", "send", "private_methods", "equal?", "type", "instance_of?", "id", "taint", "class", "instance_variables", "__send__", "protected_methods", "__id__", "frozen?", "respond_to?", "instance_eval", "===", "untaint", "clone", "singleton_methods", "instance_exec", "dup", "kind_of?", "public_methods"] Object [String, Enumerable, Comparable, Object, Kernel] ----Print the methods of the String class ["initialize"] ["upcase!", "to_str", "lstrip", "upto", "sum", "crypt", "scan", "reverse!", "==", "each_byte", "=~", "tr!", "squeeze!", "inspect", "chop", "next!", "rstrip", "casecmp", "split", "succ!", "to_f", "<", "[]=", "~", "center", "slice!", "slice", "reverse", "sub", "insert", "upcase", "tr_s!", ">", "next", "strip!", "squeeze", "dump", "count", "sub!", "hash", "lstrip!", "to_sym", "replace", "<=", "hex", "strip", "capitalize!", "length", "chop!", "each_line", "swapcase", "[]", "include?", "chomp!", "<<", "gsub", "intern", "succ", "capitalize", "oct", "+", "delete!", "initialize_copy", "rindex", "chomp", "<=>", "to_i", "eql?", "tr_s", "match", "unpack", "index", "rstrip!", "*", "delete", "gsub!", "to_s", "rjust", "%", ">=", "empty?", "size", "swapcase!", "concat", "tr", "ljust", "each", "downcase!", "downcase"] ----Pass true to recurse into parent classes ["upcase!", "to_str", "lstrip", "upto", "sum", "crypt", "scan", "reverse!", "==", "each_byte", "=~", "tr!", "squeeze!", "inspect", "chop", "next!", "rstrip", "casecmp", "split", "succ!", "to_f", "<", "[]=", "~", "center", "slice!", "slice", "reverse", "sub", "insert", "upcase", "tr_s!", ">", "next", "strip!", "squeeze", "dump", "count", "sub!", "hash", "lstrip!", "to_sym", "replace", "<=", "hex", "strip", "capitalize!", "length", "chop!", "each_line", "swapcase", "[]", "include?", "chomp!", "<<", "gsub", "intern", "succ", "capitalize", "oct", "+", "delete!", "initialize_copy", "rindex", "chomp", "<=>", "to_i", "eql?", "tr_s", "match", "unpack", "index", "rstrip!", "*", "delete", "gsub!", "to_s", "rjust", "%", ">=", "empty?", "size", "swapcase!", "concat", "tr", "ljust", "each", "downcase!", "downcase", "zip", "sort", "reject", "to_a", "find", "entries", "map", "max", "min", "each_with_index", "member?", "inject", "sort_by", "collect", "partition", "detect", "all?", "select", "grep", "find_all", "any?", "between?", "methods", "freeze", "extend", "object_id", "nil?", "method", "tainted?", "is_a?", "instance_variable_get", "instance_variable_defined?", "instance_variable_set", "display", "send", "private_methods", "equal?", "type", "instance_of?", "id", "taint", "class", "instance_variables", "__send__", "protected_methods", "__id__", "frozen?", "respond_to?", "instance_eval", "===", "untaint", "clone", "singleton_methods", "instance_exec", "dup", "kind_of?", "public_methods"] ----Call instance methods with send() ----Use Method objects and call() ----Another way, using eval() |
| class Klass def hello(*args) "Hello " + args.join(' ') end end k = Klass.new # The following four statements are equivalent puts k.hello("gentle", "readers") #=> "Hello gentle readers" puts k.hello "gentle", "readers" #=> "Hello gentle readers" puts k.send(:hello, "gentle", "readers") #=> "Hello gentle readers" puts k.send :hello, "gentle", "readers" #=> "Hello gentle readers" |
| Hello gentle readers Hello gentle readers Hello gentle readers Hello gentle readers |
| # The following statements are
equivalent puts 2+3 puts 2+(3) puts 2.send(:+, 3) puts 2.send :+, 3 # The following statements are equivalent puts 2*3 puts 2*(3) puts 2.send(:*, 3) puts 2.send :*, 3 |
| 5 5 5 5 6 6 6 6 |
| class Hello # Constructor - invoked by Hello.new def initialize(greeting) # Instance variables start with @ @greeting = greeting end def my_hello(name) @completegreeting = "#{@greeting} #{name}" end end hello_instance = Hello.new("Hello") # The following statements are equivalent puts hello_instance.my_hello("Boston!") puts hello_instance.my_hello "Boston!" puts hello_instance.send(:my_hello, "Boston") puts hello_instance.send :my_hello, "Boston" |
| Hello Boston! Hello Boston! Hello Boston! Hello Boston! |
| puts "----Define Hello class" class Hello # Constructor - invoked by Hello.new def initialize(greeting) # Instance variables start with @ @greeting = greeting end def my_hello_method1(name) @completegreeting = "#{@greeting}1 #{name}" end def my_hello_method2(name) @completegreeting = "#{@greeting}2 #{name}" end def my_hello_method3(name) @completegreeting = "#{@greeting}3 #{name}" end end puts "----Create an object instance of Hello class and call a method of it" hello_instance = Hello.new("Hello") # Simulate the set of methods you want to call during runtime methods_array = ["my_hello_method1", "my_hello_method2", "my_hello_method3"] puts "----Call a method using send passing name of a method as a parameter" methods_array.each do |x| puts hello_instance.send(x, "Boston") end |
| ----Define Hello class ----Create an object instance of Hello class and call a method of it ----Call a method using send passing name of a method as a parameter Hello1 Boston Hello2 Boston Hello3 Boston |
| # The Duck class class Duck def quack puts "Duck is quacking!" end end # The Mallard class class Mallard def quack puts "Mallard is quacking!" end end # If it quacks like a duck, it must be duck def quack_em(ducks) ducks.each do |duck| if duck.respond_to? :quack duck.quack end end end birds = [Duck.new, Mallard.new, Object.new] puts "----Call quack method for each item of the birds array. Only Duck and Mallard should be quacking." quack_em(birds) |
| ----Call quack method for each
item of the birds array. Only Duck and Mallard should be quacking. Duck is quacking! Mallard is quacking! |
In this exercise, you have learned
dynamic typing feature of Ruby language.
Leaning point: If a method that is not existent in a
class is invoked, NoMethodError exception
will be generated.| # When you send a message to an
object, the object executes the first method # it finds on its method lookup path with the same name as the message. If it # fails to find any such method, it raises a NoMethodError exception - unless # you have provided the object with a method called method_missing. The # method_missing method is passed the symbol of the nonexistent method, and # any arguments that were passed in. class Dummy end puts "----Call a method that does not exist in the Dummy class and expect NoMethodError exception." dummy = Dummy.new dummy.call_a_method_that_does_not_exist |
| ----Call a method that does not
exist in the Dummy class and expect NoMethodError exception. C:\handsonlabs\ruby_meta\samples\RubyMeta_MethodMissing_Error\lib\main.rb:13: undefined method `a_method_that_does_not_exist' for #<Dummy:0x19eda2c> (NoMethodError) |

Leaning point: If method_missing(m, *args) method is
defined in a class, it will be
called (instead of NoMethodError exception
being generated) when a method that does not exist is invoked.| class Dummy def method_missing(m, *args) puts "There's no method called #{m} here -- so method_missing method is called." puts " with arguments #{args}" end end puts "----Call a method that does not exist in the Dummy class and observe that the method_missing is called." dummy = Dummy.new dummy.a_method_that_does_not_exist dummy.a_method_that_does_not_exist(3) dummy.a_method_that_does_not_exist(3, " Sang Shin ", Time.now) |
| ----Call a method that does not
exist in the Dummy class and observe that the method_missing is called. There's no method called a_method_that_does_not_exist here -- so method_missing method is called. with arguments There's no method called a_method_that_does_not_exist here -- so method_missing method is called. with arguments 3 There's no method called a_method_that_does_not_exist here -- so method_missing method is called. with arguments 3 Sang Shin Thu Jul 03 12:44:18 -0400 2008 |
Leaning point: How Rails' find_by_xxxx() finder method is
implemented through method_missing.| class Finder def find(name) puts "find(#{name}) is called" end def method_missing(name, *args) if /^find_(.*)/ =~ name.to_s return find($1) end super end end puts "----Call a method that does not exist in the Finder class and observe that the method_missing is called." f = Finder.new f.find("Something") f.find_by_last_name("Shin") f.find_by_title("Technology Architect") |
| ----Call a method that does not
exist in the Finder class and observe that the method_missing is called. find(Something) is called find(by_last_name) is called find(by_title) is called |
Leaning point: How
Roman-to-Integer conveter is implemented through method_missing.| class
Roman # Maps roman numeral digits to their integer values DIGITS = { 'I' => 1, 'V' => 5, 'X' => 10, 'L' => 50, 'C' => 100, 'D' => 500, 'M' => 1000, } # ... def roman_to_integer(roman_string) last = nil roman_string.to_s.upcase.split(//).reverse.inject(0) do |memo, digit| if digit_value = DIGITS[digit] if last && last > digit_value memo -= digit_value else memo += digit_value end last = digit_value end memo end end def method_missing(method) str = method.id2name roman_to_integer(str) end end r = Roman.new puts "----Convert Roman to Integer using method_missing" puts r.IV #=> 4 puts r.XXIII #=> 23 puts r.MM #=> 2000 |
| ----Convert Roman to Integer
using method_missing 4 23 2000 |
Learning point: How a Proxy object
can be created through method_missing and used to invoke methods of
existing classes.| # Define Proxy class class Proxy def initialize(object) @object = object end def method_missing(symbol, *args) # Call a method whose name is the value of symbol parameter @object.send(symbol, *args) end end puts "----Create an array object." object = ["a", "b", "c"] puts "----Create a Proxy object with instance variable @object is set with array object" proxy = Proxy.new(object) puts "----Call first method of the Proxy object, which has not been defined before. So the method_missing(..) method is called with the symbol set with first. Within the method_missing(..) method, the @object is set to the array object and the symbol is set to first. So it is the same thing as calling first method of the array object. So you will see a as a result." puts proxy.first puts "----Call last method, which has not been defined before" puts proxy.last puts "----Create a String object" object2 = String.new("Ruby on Rails Programming with Passion!") puts "----Create a Proxy object with instance variable @object is set with array object" proxy2 = Proxy.new(object2) puts "----Call upcase method of String class" puts proxy2.upcase puts "----Call swapcase method of String class" puts proxy2.swapcase |
| ----Create an array object. ----Create a Proxy object with instance variable @object is set with array object ----Call first method of the Proxy object, which has not been defined before. So the method_missing(..) method is called with the symbol set with first. Within the method_missing(..) method, the @object is set to the array object and the symbol is set to first. So it is the same thing as calling first method of the array object. So you will see a as a result. a ----Call last method, which has not been defined before c ----Create a String object ----Create a Proxy object with instance variable @object is set with array object ----Call upcase method of String class RUBY ON RAILS PROGRAMMING WITH PASSION! ----Call swapcase method of String class rUBY ON rAILS pROGRAMMING WITH pASSION! |
In this exercise, you have learned basic
features of method_missing.
Learning point: How
define_method is used.
Tasks to be performed:| class
Love define_method(:my_hello) do |arg1, arg2| puts "#{arg1} loves #{arg2}" end end love = Love.new love.my_hello("Sang Shin", "Young Shin") |
| ----Call a method that is
defined via define_method Sang Shin loves Young Shin |
Leaning point: define_method can
be used to create a new method during runtime. In this example,
the name of the to-be-created method is entered by a user.| puts
"----Get a method name from a user. Type something in the Output
window and press Enter." $my_method = gets puts "----Define Love class which has define_method" class Love define_method $my_method.intern do |arg1, arg2| puts "#{$my_method} method is being invoked" puts "#{arg1} loves #{arg2}" end end puts "----Create an instance of Love class" love = Love.new puts "----Invoke a method that was dynamically defined" love.send($my_method, "Daniel", "Yina") |



| ----Get a
method name from a user. Type something in the Output window and
press Enter. whatever ----Define Love class which has define_method ----Create an instance of Love class ----Invoke a method that was dynamically defined whatever method is being invoked Daniel loves Yina |
| class
A def fred puts "In Fred" end def create_method(name, &block) self.class.send(:define_method, name, &block) end define_method(:wilma) { puts "Charge it!" } end class B < A define_method(:barney, instance_method(:fred)) end a = B.new puts "----a.barney is equivalent to a.fred" a.barney puts "----a.wilma is equivalent to a.wilma" a.wilma puts "----a.create_method(:betty) { p self }" a.create_method(:betty) { p self } puts "----a.betty" a.betty |
| ----a.barney is equivalent to
a.fred In Fred ----a.wilma is equivalent to a.wilma Charge it! ----a.create_method(:betty) { p self } ----a.betty C:\handsonlabs\ruby_meta\samples\RubyMeta_DefineMethod3\lib\main.rb:27: private method `betty' called for #<B:0x16d2702> (NoMethodError) |
In this exercise, you have learned
how to use define_method.
| puts my_instance.method1 puts my_instance.whatever puts my_instance.m545 |
| method1 method has 7 characters whatever method has 8 characters m545 has 4 characters |