Ruby Interview Questions
There are three ways to invoke a method in ruby. Can you give me at least two?
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
What is a module? Can you tell me the difference between classes and modules?
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Explain this ruby idiom: a ||= b
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
What is the primary difference in these two code snippets?
// Java
public boolean isEmpty(String s)
{
return s.length() == 0;
}
# ruby
def empty?(s)
return s.size == 0
end
The Java method only accepts Strings as arguments and only returns a boolean while... The ruby method accepts any Object and could return anything, but in this case will return a boolean if executed without exceptions.
What does accessing a class via :: (double colon) means?
:: is used to access static methods that do not require object initialization.
What will val1 and val2 equal after the code below is executed? Explain your answer.
val1 = true and false # hint: output of this statement in IRB is NOT value of val1!
val2 = true && false
Although these two statements might appear to be equivalent, they are not, due to the order of operations. Specifically, the and and or operators have lower precedence than the = operator, whereas the && and || operators have higher precedence than the = operator, based on order of operations.
To help clarify this, here’s the same code, but employing parentheses to clarify the default order of operations:
(val1 = true) and false # results in val1 being equal to true val2 = (true && false) # results in val2 being equal to false
This is, incidentally, a great example of why using parentheses to clearly specify your intent is generally a good practice, in any language. But whether or not you use parentheses, it’s important to be aware of these order of operations rules and to thereby ensure that you are properly determining when to employ and / or vs. && / ||.
Write a function that sorts the keys in a hash by the length of the key as a string. For instance, the hash:
{ abc: 'hello', 'another_key' => 123, 4567 => 'third' }
should result in:
["abc", "4567", "another_key"]
As is always true in programming, there are in fact multiple ways to accomplish this.
The most straightforward answer would be of the form:
hsh.keys.map(&:to_s).sort_by(&:length)
or:
hsh.keys.collect(&:to_s).sort_by { |key| key.length }
Alternatively, Ruby’s Enumerable mixin provides many methods to operate on collections. The key here is to turn the hash keys into a collection, convert them all to strings, then sort the array.
def key_sort hsh hsh.keys.collect(&:to_s).sort { |a, b| a.length <=> b.length } end
An equivalent call of the collect method is done with the usual block syntax of:
collect { |x| x.to_s }
Consider the following two methods:
def times_two(arg1);
puts arg1 * 2;
end
def sum(arg1, arg2);
puts arg1 + arg2;
end
What will be the result of each of the following lines of code:
times_two 5
times_two(5)
times_two (5)
sum 1, 2
sum(1, 2)
sum (1, 2)
The first three lines of code will all print out 10, as expected.
The next two lines of code will both print out 3, as expected.
However, the last line of code (i.e., sum (1,2)) will result in the following:syntax error, unexpected ',', expecting ')' sum (1, 2) ^
The problem is the space between the method name and the open parenthesis. Because of the space, the Ruby parser thinks that (1, 2) is an expression that represents a single argument, but (1, 2) is not a valid Ruby expression, hence the error.
Note that the problem does not occur with single argument methods (as shown with our timesTwo method above), since the single value is a valid expression (e.g., (5) is a valid expression which simply evaluates to 5).
Difference between a proc and lambda
Lambdas check the number of arguments, while procs do not
lam = lambda { |x| puts x } # creates a lambda that takes 1 argument lam.call(2) # prints out 2 lam.call # ArgumentError: wrong number of arguments (0 for 1) lam.call(1,2,3) # ArgumentError: wrong number of arguments (3 for 1)
In contrast, procs don’t care if they are passed the wrong number of arguments.proc = Proc.new { |x| puts x } # creates a proc that takes 1 argument proc.call(2) # prints out 2 proc.call # returns nil proc.call(1,2,3) # prints out 1 and forgets about the extra arguments
Lambdas and procs treat the ‘return’ keyword differently
‘return’ inside of a lambda triggers the code right outside of the lambda codedef lambda_test lam = lambda { return } lam.call puts "Hello world" end lambda_test # calling lambda_test prints ''Hello World''
`return` inside of a proc triggers the code outside of the method where the proc is being executeddef proc_test proc = Proc.new { return } proc.call puts "Hello world" end proc_test # calling proc_test prints nothing
What does this say about the advantages of ruby''s dynamic (duck) typed system?
That ruby program use less code and are more flexible.
What are some disadvantages (real and potential)?
Developers cannot be 100% certain that all arguments sent this empty? method will have a size method that is publicly accessible. Also, ruby is an interpreted language and it may take longer to run than compiled programs, such as Java, that are programmed similarly.
What could a developer do to address these disadvantages?
She could write unit tests or specs to ensure her application behaves as intended. She could also profile her application with tools like the unix time command, the ruby Benchmark class, and the ruby library called ruby-prof.
A cunning programmer would also argue that these two techniques ought to be used for both static and dynamic languages when developing complex systems.
Wrapping things up
To finish up with, I like to lob in some easy ones again. Plus I like to scratch my own curiosity about a candidates relationship with the ruby community.
What is your favorite api resource for ruby?
I really like gotAPI -- auto-complete searching for both ruby and rails together!
In Ruby code, you quite often see the trick of using an expression like
array.map(&:method_name)
as a shorthand form of
array.map { |element| element.method_name }
How exactly does it work?
When a parameter is passed with & in front of it (indicating that is it to be used as a block), Ruby will call to_proc on it in an attempt to make it usable as a block. Symbol #to_proc quite handily returns a Proc that will invoke the method of the corresponding name on whatever is passed to it, thus enabling our little shorthand trick to work.
What does self mean?
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Write a single line of Ruby code that prints the Fibonacci sequence of any length as an array.
(Hint: use inject)
There are multiple ways to do this, but one possible answer is:
(1..20).inject( [0, 1] ) { | fib | fib << fib.last(2).inject(:+) }
As you go up the sequence fib, you sum, or inject(:+), the last two elements in the array and add the result to the end of fib.
Consider the following code:
VAL = 'Global'
module Foo
VAL = 'Foo Local'
class Bar
def value1
VAL
end
end
end
class Foo::Bar
def value2
VAL
end
end
What will be the value of each of the following:
Foo::Bar.new.value1
Foo::Bar.new.value2
Explain your answer.
Foo::Bar.new.value1 will be equal to 'Foo Local' and Foo::Bar.new.value2 will be equal to 'Global'.
Here’s why:
The module keyword (as well as the class and def keywords) will create a new lexical scope for all of its contents. The above module Foo therefore creates the scope Foo in which the VAL constant equal to 'Foo Local' is defined. Inside Foo, we declare class Bar, which creates another new lexical scope (named Foo::Bar) which also has access to its parent scope (i.e., Foo) and all of its constants.
However, when we then declare Foo::Bar (i.e., using ::), we are actually creating yet another lexical scope, which is also named Foo::Bar (how’s that for confusing!). However, this lexical scope has no parent (i.e., it is entirely independent of the lexcial scope Foo created earlier) and therefore does not have any access to the contents of the ‘Foo’ scope. Therefore, inside class Foo::Bar, we only have access to the VAL constant declared at the beginning of the script (i.e., outside of any module) with the value 'Global'.
Is the line of code below valid Ruby code? If so, what does it do? Explain your answer.
-> (a) {p a}["Hello world"]
Yes, it’s valid. Here’s how to understand what it does:
The -> operator creates a new Proc, which is one of Ruby’s function types. (The -> is often called the “stabby proc”. It’s also called the “stabby lambda”, as it creates a new Proc instance that is a lambda. All lambdas are Procs, but not all Procs are lambdas. There are some slight differences between the two.)
This particular Proc takes one parameter (namely, a). When the Proc is called, Ruby executes the block p a, which is the equivalent of puts(a.inspect) (a subtle, but useful, difference which is why p is sometimes better than puts for debugging). So this Proc simply prints out the string that is passed to it.
You can call a Proc by using either the call method on Proc, or by using the square bracket syntax, so this line of code also invokes the Proc and passes it the string “Hello World”.
So putting that all together, this line of code (a) creates a Proc that takes a single parameter a which it prints out and (b) invokes that Proc and passes it the string “Hello world”. So, in short, this line of code prints “Hello World”.
What is the difference between calling super and calling super()?
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.
(Thanks to Ruby Gotchas for this question.)
Given:
x = "hello"
Explain the difference between:
x += " world"
and
x.concat " world"
The += operator re-initializes the variable with a new value, so a += b is equivalent to a = a + b.
Therefore, while it may seem that += is mutating the value, it’s actually creating a new object and pointing the the old variable to that new object.
This is perhaps easier to understand if written as follows:
foo = "foo" foo2 = foo foo.concat "bar" puts foo => "foobar" puts foo2 => "foobar" foo += "baz" puts foo => "foobarbaz" puts foo2 => "foobar"
(Examining the object_id of foo and foo2 will also demonstrate that new objects are being created.)
The difference has implications for performance and also has different mutation behavior than one might expect.
What does the “$” character mean in Ruby?
$ identifies a global variable, as opposed to a local variable, @instance variable, or @@class variable. This is one of the pre-defined Ruby global variables. All globals are prefixed with $, and in this case $$ represents the current process ID. This was inherited from Perl.
What is the difference between clone and dup methods in Ruby?
clone
copies the singleton class, whiledup
does not.o = Object.new def o.foo 42 end o.dup.foo # raises NoMethodError o.clone.foo # returns 42
Second,
clone
preserves the frozen state, whiledup
does not.class Foo attr_accessor :bar end o = Foo.new o.freeze o.dup.bar = 10 # succeeds o.clone.bar = 10 # raises RuntimeError
What is a Proc?
Everyone usually confuses procs with blocks, but the strongest rubyist can grok the true meaning of the question.
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).
Note: Procs and lambdas do have subtle, but important, differences in ruby v1.8.6. However, I wouldn''t expect a candidate talk about these nitty-gritty details during an interview. (Kudos to Noah Thorp)# wants a proc, a lambda, AND a block def three_ways(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_ways(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??? #=> # # #
Which of the expressions listed below will result in "false"?
true ? "true" : "false"
false ? "true" : "false"
nil ? "true" : "false"
1 ? "true" : "false"
0 ? "true" : "false"
"false" ? "true" : "false"
"" ? "true" : "false"
[] ? "true" : "false"
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
What is unit testing (in classical terms)? What is the primary technique when writing a test?
The strongest candidates should be quite comfortable with test or behavior driven development.
Unit testing, simply put, is testing methods -- the smallest unit in object-oriented programming. Strong candidates will argue that it allows a developer to flesh out their API before it''s consumed by other systems in the application.
The primary way to achieve this is to assert that the actual result of the method matches an expected result.require "test/unit" class Brokened def uh_oh "I needs fixing" end end class BrokenedTest < Test::Unit::TestCase def test_uh_oh actual = Brokened.new assert_equal("I''m all better!", actual.uh_oh) end end #=> Started #=> F #=> Finished in 0.663831 seconds. #=> #=> 1) Failure: #=> test_uh_oh:11 #=> <"I''m all better!"> expected but was #=> <"I needs fixing">. #=> #=> 1 tests, 1 assertions, 1 failures, 0 errors
Show me the money!
Variable typing is one of those topics that everyone sort of understands it, but is hard to put it into words. I''ve iterated and improved the next series of questions to really test a senior level candidate''s knowledge of static and dynamic typing. This is my best attempt so far.
Explain each of the following operators and how and when they should be used: ==, ===, eql?, equal?.
== Checks if the value of two operands are equal (often overridden to provide a class-specific definition of equality).
=== Specifically used to test equality within the when clause of a case statement (also often overridden to provide meaningful class-specific semantics in case statements). === is the pattern matching operator!
=== matches regular expressions
=== checks range membership
=== checks being instance of a class
=== calls lambda expressions
=== sometimes checks equality, but mostly it does not
Some examplescase value when /regexp/ # value matches this regexp when 4..10 # value is in range when MyClass # value is an instance of class when ->(value) { ... } # lambda expression returns true when a, b, c, d # value matches one of a through d with `===` when *array # value matches an element in array with `===` when x # values is equal to x unless x is one of the above end
eql? Checks if the value and type of two operands are the same (as opposed to the == operator which compares values but ignores types). For example, 1 == 1.0 evaluates to true, whereas 1.eql?(1.0) evaluates to false.
equal? Compares the identity of two objects; i.e., returns true iff both operands have the same object id (i.e., if they both refer to the same object). Note that this will return false when comparing two identical copies of the same object.
(Thanks to Ruby Gotchas for this question.)
gem vs engine vs plugin
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
What is an object?
An instance of a class.
To some, it''s also the root class in ruby (Object).
Classes themselves descend from the Object root class. (Kudos to Ezra)
Difference between map, collect, select, reject, each, inject, reduce, find and detect methods in ruby?
map (collect)
map takes the enumerable object and a block, evaluates the block for each element and then return a new array with the calculated values. The original array is not modified. The collect method is same as map.a = [1,2,3,4,5] a.map{ |e| e * 2 } # => [2,4,6,8,10]
If you are try to use map to select any specific values like where e %2 == 0 then it will evaluate each element and will output only the result which will be either true or false
[1,2,3,4,5].map{ |e| e %2 == 0 } # => [false, true, false, true, false]
collect
Alias for mapselect
select evaluates the block with each element for which the block returns true.
[1,2,3,4,5,6,7,8,9,10].select{ |e| e > 5 } # => [6 ,7, 8, 9, 10]
select would also return an element for which the statement is true.[1,2,3,4,5,6,7,8,9,10].select{ |e| e * 3 } # => [1,2,3,4,5,6,7,8,9,10]
reject
The opposite of select. reject method runs an expression for each array element and returns an array of elements for which the expression is false.
[1,2,3,4,5,6,7,8,9,10].reject{|e| e % 2 == 0 } # returns [1, 3, 5, 7, 9]
each
Executes an action using as parameter each element of the array. Returns the unmodified array.
[1,2,3,4,5,6,7,8,9,10].each{|e| print e.to_s+"!" } # prints "1!2!3!4!5!6!7!8!9!10!" # returns [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
inject (reduce)
Takes an accumulator (sum) and changes it as many times as there are elements in the array. Returns the final value of the accumulator.
[6,7,8,9,10].inject(15){ |sum, e| sum += e } # => 55
If you do not explicitly specify an initial value for accumlator, the inject method uses the first element of collection as the initial value of the accumulator.[1,2,3,4,5].inject{ |sum, e| sum += e } # => 15
reduce
Alias for inject
find
Take an expression and returns the first element for which the expression is true:
[1,2,3,4,5,6,7,8,9,10].find{|e| e % 2 == 0} # returns 2
Detect
Alias for find
Can you tell me the three levels of method access control for classes and modules? What do they imply about the method?
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.
class AccessLevel def something_interesting another = AccessLevel.new another.public_method another.protected_method another.private_method end def public_method puts "Public method. Nice to meet you." end protected def protected_method puts "Protected method. Sweet!" end private def private_method puts "Incoming exception!" end end AccessLevel.new.something_interesting #=> Public method. Nice to meet you. #=> Protected method. Sweet! #=> NoMethodError: private method ‘private_method’ called for #=> #
What is a class?
A text-book 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.