Authored on Sep 2015
To make sure we hire a top class rubyist, and -- to select the cream of the crop -- these set of questions are specifically written for such interview, kind of ruby benchmark. Hiring a candidate who has the correct grasp on the concepts in 30 minutes of the interview duration is a challenge altogether. I hope this help all folks.
Our expectations are generally high while interviewing and candidates will give you a variety of responses based on their experience and knowledge. So it's up to the interviewer to decide the correctness of the answers.
There can be many possible approaches to these questions -- some aren't mentioned here. This list is not complete, by any means and I welcome your suggestions to this.
Short answer: symbols are immutable and reusable, retaining the same object_id.
Be prepared to discuss the benefits of using symbols vs. strings, the effect on memory usage, and in which situations you would use one over the other.
Here’s your chance to show off your theoretical knowledge and demonstrate that you can have an in depth conversation on class hierarchies, inheritance, methods, encapsulation, polymorphism, and more.
Parrot answer: classes are a blue-print for constructing computer models for real or virtual objects... boring.
In reality: classes hold data, have methods that interact with that data, and are used to instantiate objects.
Like this.
class WhatAreClasses
def initialize
@data = "I'm instance data of this object. Hello."
end
def method
puts @data.gsub("instance", "altered")
end
end
object = WhatAreClasses.new
object.method
#=> I'm altered data of this object. Hello.
Parrot answer : An instance of a class.
It's also the root class in ruby (Object). Classes themselves descend from the Object root class.
Modules serve as a mechanism for namespaces.
module ANamespace
class AClass
def initialize
puts "Another object, coming right up!"
end
end
end
ANamespace::AClass.new
#=> Another object, coming right up!
Also, modules provide as a mechanism for multiple inheritance via mix-ins and cannot be instantiated like classes can.
All methods, no matter the access control, can be accessed within the class. But what about outside callers?
Public methods enforce no access control -- they can be called in any scope.
Protected methods are only accessible to other objects of the same class.
Private methods are only accessible within the context of the current object.
object = Object.new
puts object.object_id
#=> 282660
puts object.send(:object_id)
#=> 282660
puts object.method(:object_id).call
#=> 282660
a = 1
b = 2
a ||= b #=> a = 1
a = nil
b = 2
a ||= b #=> a = 2
a = false
b = 2
a ||= b #=> a = 2
Essentially, Procs are anonymous methods (or nameless functions) containing code. They can be placed inside a variable and passed around like any other object or scalar value. They are created by Proc.new, lambda, and blocks (invoked by the yield keyword).
# wants a proc, a lambda, AND a block
def three_approaches(proc, lambda, &block)
proc.call
lambda.call
yield # like block.call
puts "#{proc.inspect} #{lambda.inspect} #{block.inspect}"
end
anonymous = Proc.new { puts "I'm a Proc for sure." }
nameless = lambda { puts "But what about me?" }
three_approaches(anonymous, nameless) do
puts "I'm a block, but could it be???"
end
#=> I'm a Proc for sure.
#=> But what about me?
#=> I'm a block, but could it be???
#=> #<Proc:0x00089d64> #<Proc:0x00089c74> #<Proc:0x00089b34>
Unit testing, simply put, is testing methods -- the smallest unit in object-oriented programming. The primary way to achieve this is to assert that the actual result of the method matches an expected result.
require "test/unit"
class Greet
def say
"Hello ruby"
end
end
class GreetTest < Test::Unit::TestCase
def test_say
greet = Greet.new
assert_equal("Hello!", greet.say)
end
end
#=> Started
#=> F
#=> Finished in 0.663831 seconds.
#=>
#=> 1) Failure:
#=> test_say:11
#=> <"Hello!"> expected but was
#=> <"Hello ruby">.
#=>
#=> 1 tests, 1 assertions, 1 failures, 0 errors
A call to super invokes the parent method with the same arguments that were passed to the child method. An error will therefore occur if the arguments passed to the child method don’t match what the parent is expecting.
A call to super() invokes the parent method without any arguments, as presumably expected. As always, being explicit in your code is a good thing.
Require() loads and processes the Ruby code from a separate file, including whatever classes, modules, methods, and constants are in that file into the current scope.
Load() performs the inclusion operation once, it reprocesses the code every time load is called.
Please share your ideas / feedback with us!