Ruby Meta Programming Interview Questions

Implement a fancier version of attr_accessor that includes validation. Complete the attr_validated code below so that the unit tests pass.

require 'test/unit'

class Dog

    def self.attr_validated(method_name, &validation)
        # Complete this method so that the unit tests pass
    end

    attr_validated :num_legs do |v|
        v <= 4
    end


end

class TestDog < Test::Unit::TestCase

    def test_good_value
        dog = Dog.new
        dog.num_legs = 3

        assert_equal 3, dog.num_legs
    end

    def test_nil_value
        dog = Dog.new
        assert_raises ArgumentError do
            dog.num_legs = nil
        end
    end

    def test_illegal_value
        dog = Dog.new
        assert_raises ArgumentError do
            dog.num_legs = 5
        end
    end

end

The following code will fail with NoMethodError : private method 'dream' called for Dog

Assuming that you cannot modify the source code for the Dog class and that the method
must remain private - how can you nonetheless call this method from outside of Dog class?

class Dog
    def speak
        puts "woof"
    end

    private

    def dream
        puts "chasing a rabbit"
    end
end

dog = Dog.new
dog.speak
dog.dream

Suppose you have a class Dog with two methods GetHasSpots and say_Woof. The method names do not follow your new naming conventions and you wish to rename them to has_spots? and say_woof. However, finding and correcting all references to these methods in one coding session is impractical due to a very large code base.

Thus, for some interim period of time you wish to allow both the old method names and the new methods names to work. Of course, you want to do this in the most DRY way possible, while also clearly marking the old methods as deprecated. The shell of a solution is shown below. Fill in the details of the deprecate method to make the unit tests pass.

require 'test/unit'

class Dog

    def has_spots?
        true
    end

    def woof
        "woof"
    end

    def self.deprecate(old_method, new_method)
       # Add code here that will make the unit test pass
    end

    deprecate :say_Woof, :woof
    deprecate :GetHasSpots, :has_spots?
end

class TestDog < Test::Unit::TestCase

    def test_deprecation
        dog = Dog.new
        assert_equal true, dog.GetHasSpots
        assert_equal "woof", dog.say_Woof
    end

end

Modify the + operator in Ruby so that it always adds an extra (i.e1+1=3`). When you are done the unit test below should pass.

Hint: remember that the + operator is really a method with signature def +(value) on the Fixnum class.

require 'test/unit/'

class BackToKindergartenTest < Test::Unit::TestCase
    def test_plus_one
        assert_equal 3, 1 + 1
        assert_equal 5, 2 + 2
        assert_equal 1, -1 + 1
    end
end