Question | Click to View Answer |
What does the following code print? Explain. class Books; end
b = Books.new
p b.hi
|
This code raises the following exception: NoMethodError: undefined method `hi' for #Books:0x007faf6b1e7950 Ruby goes through the ancestor hierarchy and looks for a method that corresponds with the message :hi. It does not encounter a corresponding method, so it calls BasicObject#method_missing, which raises the NoMethodError exception. |
What does the following code print? Explain. class Charger
private
def method_missing(name, *args)
"I'm a little teapot"
end
end
p Charger.new.whoo_hoo
|
"I'm a little teapot"
No classes respond to the :whoo_hoo message in the charger ancestor hierarchy, so method_missing is called. This example defines Charger#method_missing, which returns a value before BasicObject#method_missing can be called to raise an exception. |
What does the following code print? Explain. class A
private
def method_missing(name, *args)
args.unshift(name.to_s).join
end
end
p A.new.meta('programming', 'ruby')
|
"metaprogrammingruby"
The name parameter is assigned to the method name (:meta) and args is assigned to an array of the arguments (['programming', 'ruby']). |
Use method_missing to sum the arguments passed to the :add method. class Calc
private
def method_missing(name, *args)
# add code here
end
end
Calc.new.add(1, 2, 3, 4) # should return 10
|
class Calc
private
def method_missing(name, *args)
args.inject(&:+)
end
end
Calc.new.add(1, 2, 3, 4) # => 10
|
Update the following code to raise an exception if the message is anything other than :full_name. class Person
private
def method_missing(name, *args)
args.join(" ")
end
end
Person.new.full_name("Fat", "Joe") # => "Fat Joe"
Person.new.whatever("bob", "lob") # => raise exception
|
class Person
private
def method_missing(name, *args)
super unless name == :full_name
args.join(" ")
end
end
It's usually a bad idea to always override method_missing. Using super to raise exceptions for unexpected messages is almost always a good idea. |
What problem does the following code highlight? class Calculator
private
def method_missing(name, *args)
super unless name == :multiply
args.inject(&:*)
end
end
calc = Calculator.new
p calc.respond_to? :multiply
|
false
The calc object is lying to us by saying it does not respond to the :multiply message. |
What problem does the following code highlight? class Monster
private
def method_missing(name, *args)
"blah monster, attack!"
end
end
krumm = Monster.new
krumm.method :boo
|
This raises the following exception: NameError: undefined method The method method is misleading us by raising and exception and suggesting that the krumm object does not respond to the :boo message. |
What does the following example print? Explain. class Redwall
private
def method_missing(name, *args)
super unless name == :battle_cry
"Eulalia"
end
def respond_to_missing?(name, include_private = false)
name == :battle_cry || super
end
end
best_book = Redwall.new
p best_book.respond_to? :battle_cry
p !!best_book.method(:battle_cry)
|
true
true
The respond_to_missing? method can be overwritten to have the respond_to? and method() methods behave properly. |
What does the following code print? Explain. class Object
private
def method_missing(name, *args)
'This is a terrible idea'
end
end
p 'string'
p 'boo'.fooey
p 'array'
p [].boggie_down
|
'string'
'This is a terrible idea'
'array'
'This is a terrible idea'
Object#method_missing is called before the default BasicObject#method_missing can be called. This code would return 'This is a terrible idea' for almost all messages sent to objects that inherit from Object cannot respond to. It's terrible code, but illustrates the method_missing lookup process and how instances of different classes can share the same method_missing. |
Fix the sneaky little bug in this program? Why is the code raising the SystemStackError: stack level too deep exception? class Seltzer
private
def method_missing(name, *args)
result = 'non-alcoholic bubbly'
3.times { result << fun }
result
end
end
p Seltzer.new.drank
|
The code accidentally used fun instead of "fun". When method_missing is not overridden, using an undefined local variable or method will raise an exception that's easy to decipher. When the program encounters fun, it interprets it as a method call and calls method_missing again. This process continues infinitely until the program realizes it's going in an infinite loop and raises a SystemStackError exception. Falling back on super for unexpected inputs is the best way to avoid these cryptic exceptions. class Seltzer
private
def method_missing(name, *args)
super unless name == :drank
result = 'non-alcoholic bubbly'
3.times { result << fun }
result
end
end
|
Add code to method missing so it will respond with values assigned to instance variables for instances of the Book class. class Book
def initialize(title, author)
@title = title
@author = author
end
private
def method_missing(name, *args)
# add code here
end
end
b = Book.new("The Intelligent Investor", "Benjamin Graham")
b.title # => "The Intelligent Investor"
b.author # => "Benjamin Graham"
|
def method_missing(name, *args)
iv = "@#{name.to_s}"
super unless instance_variables.include?(iv.to_sym)
instance_variable_get(iv)
end
|