assert_equal 'STRING', "STRING".to_s
assert_equal '"STRING"', "STRING".inspect
- open class: a class that is re-declared to add funcitonality
class BullDog < Dog
def bark
super + ", GROWL"
end
end
def test_subclasses_can_invoke_parent_behavior_via_super
ralph = BullDog.new("Ralph")
assert_equal 'WOOF, GROWL', ralph.bark
end
super calls parent method of same name
class GreatDane < Dog
def growl
super.bark + ", GROWL"
end
end
def test_super_does_not_work_cross_method
george = GreatDane.new("George")
assert_raise(NoMethodError) do
george.growl
end
end
<NoMethodError: super: no superclass method `growl' for #<AboutInheritance::GreatDane:0x007ffa6b3648c8 @name="George">>
super does not call parent method from another method
class String
end
def test_bare_bones_class_names_assume_the_current_scope
assert_equal true, AboutScope::String == String
end
def test_nested_string_is_not_the_same_as_the_system_string
assert_equal false, String == "HI".class
end
def test_use_the_prefix_scope_operator_to_force_the_global_scope
assert_equal true, ::String == "HI".class
end
def test_you_can_define_methods_on_individual_objects
fido = Dog.new
def fido.wag
:fidos_wag
end
assert_equal :fidos_wag, fido.wag
end
def test_other_objects_are_not_affected_by_these_singleton_methods
fido = Dog.new
rover = Dog.new
def fido.wag
:fidos_wag
end
assert_raise(NoMethodError) do
rover.wag
end
end
class Dog
class << self
def another_class_method
:still_another_way
end
end
end
def test_heres_still_another_way_to_write_class_methods
assert_equal :still_another_way, Dog.another_class_method
end
# THINK ABOUT IT:
#
# The two major ways to write class methods are:
# class Demo
# def self.method
# end
#
# class << self
# def class_methods
# end
# end
# end
#
# Which do you prefer and why?
# Are there times you might prefer one over the other?
def test_heres_an_easy_way_to_call_class_methods_from_instance_methods
fido = Dog.new
assert_equal :still_another_way, fido.class.another_class_method
end
- When would you call a class method this way?
def test_send_with_underscores_will_also_send_messages
mc = MessageCatcher.new
assert_equal true, mc.__send__(:caught?)
# THINK ABOUT IT:
#
# Why does Ruby provide both send and __send__ ?
end
class MessageCatcher
def add_a_payload(*args)
args
end
end
def test_sending_a_message_with_arguments
mc = MessageCatcher.new
assert_equal [], mc.add_a_payload
assert_equal __, mc.send(:add_a_payload)
assert_equal [3, 4, nil, 6], mc.add_a_payload(3, 4, nil, 6)
assert_equal __, mc.send(:add_a_payload, 3, 4, nil, 6)
end
# NOTE:
#
# Both obj.msg and obj.send(:msg) sends the message named :msg to
# the object. We use "send" when the name of the message can vary
# dynamically (e.g. calculated at run time), but by far the most
# common way of sending a message is just to say: obj.msg.
- Why isn't the
:add_a_payload symbol not sent?
def test_calling_method_missing_causes_the_no_method_error
typical = TypicalObject.new
exception = assert_raise(NoMethodError) do
typical.method_missing(:foobar)
end
assert_match(/foobar/, exception.message)
# THINK ABOUT IT:
#
# If the method :method_missing causes the NoMethodError, then
# what would happen if we redefine method_missing?
#
# NOTE:
#
# In Ruby 1.8 the method_missing method is public and can be
# called as shown above. However, in Ruby 1.9 (and later versions)
# the method_missing method is private. We explicitly made it
# public in the testing framework so this example works in both
# versions of Ruby. Just keep in mind you can't call
# method_missing like that after Ruby 1.9 normally.
#
# Thanks. We now return you to your regularly scheduled Ruby
# Koans.
end
class AllMessageCatcher
def method_missing(method_name, *args, &block)
"Someone called #{method_name} with <#{args.join(", ")}>"
end
end
def test_all_messages_are_caught
catcher = AllMessageCatcher.new
assert_equal 'Someone called foobar with <>', catcher.foobar
assert_equal 'Someone called foobaz with <1>', catcher.foobaz(1)
assert_equal 'Someone called sum with <1, 2, 3, 4, 5, 6>', catcher.sum(1,2,3,4,5,6)
end
def test_catching_messages_makes_respond_to_lie
catcher = AllMessageCatcher.new
assert_nothing_raised do
catcher.any_method
end
assert_equal false, catcher.respond_to?(:any_method)
end
- How does catcher make
respond_to? lie?