December Code

Ruby basics interview questions, with answers

Ruby was designed to read naturally, and much of its behaviour follows from one rule: every value is an object with methods, including numbers, nil and true. Interviews for Ruby and Rails roles start with the consequences of that rule, such as which values count as false, what nil really is, and how Ruby converts and checks types without declarations.

The answers below cover Ruby's core types, truthiness, nil, conversions, ranges, type checks and the kinds of variable, with code run on Ruby 3.4. Then take the free Ruby diagnostic — ten questions across every Ruby topic in the bank — to see which of these you can explain but not yet predict.

The questions, with answers

  1. 1.What are Ruby's basic data types?

    In short: Integer, Float, String, Symbol, Array, Hash, Range, true, false and nil, and every one of them is an object with a class.

    Ruby has no primitive types: numbers, strings, symbols, arrays, hashes, ranges, true, false and nil are all objects, so 42.class returns Integer and nil.class returns NilClass. Integers grow automatically into big numbers instead of overflowing, and Floats are IEEE 754 doubles. Strings are mutable sequences of characters, symbols are immutable names, arrays are ordered lists and hashes map keys to values while keeping insertion order. Because everything is an object, you call methods on literals directly, as in 3.times or -5.abs.

    puts 42.class
    puts 4.2.class
    puts nil.class
    puts (2**70).class
    # Integer
    # Float
    # NilClass
    # Integer
  2. 2.Which values are falsy in Ruby?

    In short: Only nil and false; every other value, including 0, the empty string and the empty array, is truthy.

    Ruby's rule is short: in a condition, nil and false are false and everything else is true. That differs from C, Python, JavaScript and PHP, where 0 and empty strings are falsy, so code ported from those languages can take the wrong branch. To test for zero or emptiness, ask explicitly with methods such as zero?, empty? or nil?. The rule makes the common idiom value || default safe for 0 and "", which count as present, while a nil value falls back to the default.

    x = 0
    puts "0 is truthy" if x
    puts "nil is falsy" unless nil
    # 0 is truthy
    # nil is falsy
  3. 3.What is nil in Ruby, and what does the &. operator do?

    In short: nil is the single instance of NilClass, meaning no value; obj&.method calls the method only when obj is not nil.

    nil is an ordinary object representing the absence of a value: methods return it when there is nothing to return, and a missing hash key reads as nil. Being an object, it has methods: nil.to_s is "", nil.to_a is [] and nil.nil? is true. Calling a method that nil lacks raises NoMethodError, the Ruby equivalent of a null pointer error. The safe navigation operator, &., added in Ruby 2.3, calls the method only when the receiver is not nil and otherwise returns nil, so user&.name avoids an explicit nil check.

    name = nil
    p name.to_s
    p name&.upcase
    # ""
    # nil
  4. 4.How do you convert between numbers and strings in Ruby?

    In short: Use to_i, to_f and to_s for lenient conversion, and Integer() or Float() when malformed input should raise an error.

    Ruby never converts types implicitly in arithmetic: "3" + 1 raises a TypeError instead of guessing. Conversion is explicit. to_i and to_f parse a number from the start of a string and give 0 when there is none, to_s turns any object into a string, and 3.99.to_i truncates toward zero. The Kernel methods Integer() and Float() are strict and raise ArgumentError on malformed input, which suits user input. Floats have the usual binary rounding, so 0.1 + 0.2 == 0.3 is false; use Rational or BigDecimal for exact decimals such as money.

    puts "3.7".to_f + 1
    puts 3.99.to_i
    puts 0.1 + 0.2 == 0.3
    # 4.7
    # 3
    # false
  5. 5.What are ranges in Ruby?

    In short: A range such as 1..4 includes its end, 1...4 excludes it; ranges work in loops, slices, case branches and checks with include?.

    A range is an object describing an interval between two values. Two dots include the end value and three dots exclude it, so (1..4).to_a is [1, 2, 3, 4] while (1...4).to_a stops at 3. Ranges iterate with each, step through values with step, test membership with include? or cover?, and appear in case branches such as when 90..100. They work for any comparable values, including letters, as ('a'..'e'), and an endless range such as (1..) is useful in loops and slices.

    a = (1..4).to_a
    b = (1...4).to_a
    p a, b
    p (1..10).step(3).to_a
    # [1, 2, 3, 4]
    # [1, 2, 3]
    # [1, 4, 7, 10]
  6. 6.How do you check an object's type in Ruby?

    In short: class gives the exact class, is_a? also accepts superclasses and modules, instance_of? requires an exact match, and respond_to? checks for a method.

    n.class returns the object's class. is_a?, also spelled kind_of?, is true for the class, any superclass and any included module, so 5.is_a?(Numeric) is true. instance_of? is true only for the exact class, which is why 5.instance_of?(Numeric) is false. Idiomatic Ruby, though, prefers duck typing: instead of asking what an object is, it asks what the object can do, with respond_to?(:each) or simply by calling the method. That keeps code open to any object that behaves correctly, whatever its class.

    n = 5
    p n.is_a?(Numeric)
    p n.instance_of?(Numeric)
    p n.respond_to?(:+)
    # true
    # false
    # true
  7. 7.What kinds of variables does Ruby have?

    In short: Local variables are plain names, @x is an instance variable, @@x a class variable, $x a global, and a capitalised name a constant.

    Ruby marks a variable's kind with its first character rather than a declaration. A lowercase name is a local variable, visible only in the scope that creates it; a def starts a new scope, so a method cannot see the local variables outside it. @name is an instance variable belonging to one object, @@name a class variable shared by a class and its subclasses, and $name a global visible everywhere, which is best avoided. A name starting with a capital letter is a constant, and Ruby warns if it is reassigned. Methods can read constants and globals.

    $count = 1
    LIMIT = 3
    def show
      "#{$count}/#{LIMIT}"
    end
    puts show
    # 1/3

How the diagnostic asks it

One question from the Ruby bank, exactly as a sitting would show it. The bank has 5 on basics & types and 30 across Ruby.

Basics & Types · easyRB-001

What does this Ruby code print?

[0, "", [], nil, false].each do |v|
  print(v ? "T" : "F")
end
  1. 1TTTFFcorrect
  2. 2FFFFF
  3. 3FFTFF
  4. 4TFTFF

In Ruby exactly two values are falsy: nil and false. Everything else is truthy, including 0, the empty string and the empty array, so the loop prints T for the first three and F for the last two: TTTFF. FFFFF and FFTFF carry over the rules of C, Python or JavaScript, where 0 and the empty string are falsy; TFTFF treats only the empty string as falsy. To test for zero or emptiness in Ruby, ask explicitly, with n.zero?, s.empty? or a.empty?; code ported from Python often goes wrong here, because if list: no longer checks for an empty list.

Measure it

Reading answers tells you what’s true. A diagnostic tells you what you get wrong.

10 Ruby questions across its topics, easy to hard, about fifteen minutes. You get a readiness figure with the arithmetic shown, the topics you missed named, and a practice set sized for today. Free: 1 diagnostic a month and 15 problems a day. No card.

What the readiness test measures · how the score is computed

By Harshit · updated