10 (advanced) Ruby Interview Question
Tags: ruby, programming, career
Published: 2022-12-20 09:12:55


## [1] What is a singleton method in Ruby and how do you define one?

A singleton method is a method that is defined on a single instance of an object, rather than on the object's class as a whole. To define a singleton method, you use the define_singleton_method method and pass it the method name and a block of code that defines the method's behavior. Here is an example of defining a singleton method:

```ruby
dog = Dog.new("Fido")

def dog.bark
  puts "Woof!"
end

dog.bark # outputs "Woof!"
```

## [2] What is metaprogramming in Ruby and how does it work?

Metaprogramming in Ruby refers to the ability to write code that can generate or modify other code at runtime. This is achieved through the use of various metaprogramming techniques such as method_missing, define_method, and eval. Here is an example of using the define_method method to define a new method at runtime:

```ruby
class Dog
  def self.define_bark(breed)
    define_method(:bark) do
      puts "Woof! I am a #{breed}."
    end
  end
end

Dog.define_bark("Labrador")
dog = Dog.new
dog.bark # outputs "Woof! I am a Labrador."
```

## [3] What is a module in Ruby and how do you use them?

A module in Ruby is a collection of methods and constants that can be included in a class. Modules are used to provide additional functionality to a class without the need for inheritance. To include a module in a class, you use the include keyword followed by the module name. Here is an example of using a module:

```ruby
module Barkable
  def bark
    puts "Woof!"
  end
end

class Dog
  include Barkable
end

dog = Dog.new
dog.bark # outputs "Woof!"
```

## [4] How do you implement the observer pattern in Ruby?

The observer pattern is a design pattern in which an object (the subject) maintains a list of dependencies (observers) and notifies them when its state changes. To implement the observer pattern in Ruby, you can use the Observer library, which provides a set of classes and methods for creating observers and subjects. Here is an example of using the Observer library:

```ruby
require 'observer'

class Dog
  include Observable

  def bark
    changed
    notify_observers("barking")
  end
end

class Owner
  def update(event)
    puts "Dog is #{event}."
  end
end

dog = Dog.new
owner = Owner.new
dog.add_observer(owner)
dog.bark # outputs "Dog is barking."
```

## [5] What is the difference between a class variable and a class instance variable in Ruby?

A class variable in Ruby is a variable that is shared among all instances of a class. It is defined with the @@ symbol and is available to all methods of the class. Here is an example of using a class variable:

```ruby
class Dog
  @@num_dogs = 0

  def initialize
    @@num_dogs += 1
  end

  def self.num_dogs
    @@num_dogs
  end
end

dog1 = Dog.new
dog2 = Dog.new
puts Dog.num_dogs # outputs 2
```

A class instance variable, on the other hand, is a variable that is specific to a particular instance of a class. It is defined with the @ symbol and is only available to the instance's methods. Here is an example of using a class instance variable:


```ruby
class Dog
  def initialize(name)
    @name = name
  end

  def greet
    puts "Hello, my name is #{@name}!"
  end
end

dog1 = Dog.new("Fido")
dog1.greet # outputs "Hello, my name is Fido!"
dog2 = Dog.new("Buddy")
dog2.greet # outputs "Hello, my name is Buddy!"
```

## [6] What is the difference between the freeze and seal methods in Ruby?

The freeze method in Ruby is used to prevent an object from being modified. Once an object is frozen, any attempts to modify it will raise a RuntimeError. The seal method, on the other hand, is used to prevent an object from being modified or extended. It can be thought of as a stricter version of the freeze method. Here is an example of using the freeze and seal methods:


```ruby
string = "hello"
string.freeze
string << " world" # raises a RuntimeError

array = [1, 2, 3]
array.seal
array << 4 # raises a RuntimeError
```

## [7] What is the difference between a lazy enumerator and a regular enumerator in Ruby?

A lazy enumerator in Ruby is an enumerator that generates its values on demand, rather than generating all of the values upfront. This can be useful for working with large datasets or when only a subset of the values is needed. A regular enumerator, on the other hand, generates all of the values upfront. To create a lazy enumerator in Ruby, you can use the lazy method of the Enumerator class. Here is an example of using a lazy enumerator:


```ruby
lazy_enumerator = (1..Float::INFINITY).lazy.select { |n| n % 2 == 0 }

lazy_enumerator.take(5).to_a # outputs [2, 4, 6, 8, 10]
```

## [8] What is a method_missing in Ruby and how do you use it?

The method_missing method in Ruby is a special method that is called when a method is called on an object that does not exist. It allows you to define a custom behavior for handling missing methods. To use method_missing, you define a method_missing method in your class and use the super keyword to call the original method_missing method. Here is an example of using method_missing:

```ruby
class Dog
  def bark
    puts "Woof!"
  end

  def method_missing(method_name, *arguments, &block)
    if method_name == :fetch
      puts "Fetching the ball!"
    else
      super
    end
  end
end

dog = Dog.new
dog.bark # outputs "Woof!"
dog.fetch # outputs "Fetching the ball!"
dog.sit # raises a NoMethodError
```

In this example, the method_missing method is used to handle the fetch method if it is called on the dog object. If the method is not fetch, the super keyword is used to call the original method_missing method and raise a NoMethodError if the method does not exist.


## [9] What is the difference between a proc and a lambda in Ruby?


A proc in Ruby is a block of code that can be stored in a variable and passed around like an object. It is created using the proc keyword or the Proc.new method. A lambda is similar to a proc, but it has stricter rules for argument checking and return behavior. It is created using the lambda keyword or the -> operator. Here is an example of using a proc and a lambda:

```ruby
proc = proc { |x| puts x }
proc.call(1) # outputs 1

lambda = ->(x) { puts x }
lambda.call(1) # outputs 1
```


## [10] What is the difference between the map and collect methods in Ruby?

The map and collect methods in Ruby are both used to transform a collection of items by applying a block of code to each item and returning a new collection with the transformed items. The main difference between the two methods is that map returns a new array, while collect returns a new object of the same type as the original collection. Here is an example of using the map and collect methods:

```ruby
array = [1, 2, 3]

new_array = array.map { |x| x * 2 }
# new_array is [2, 4, 6]

hash = { a: 1, b: 2, c: 3 }

new_hash = hash.collect { |k, v| [k, v * 2] }.to_h
# new_hash is { a: 2, b: 4, c: 6 }
```