DEV Community

Cover image for Ruby interview questions
Andrew Molchanov
Andrew Molchanov

Posted on

Ruby interview questions

In this post, I've created a collection of Ruby basics for a Middle-level developer.

In common cases, interviewers have a pre-prepared set of tasks. While others prefer a conversation about experience mixed with technical questions. On the other hand, some companies care most about soft skills. But all of these understand one thing correctly. An interview is a costly process. All companies want to decrease costs.

After interviewing for many companies, there is an understanding that the candidate should know and be able to apply the basic principles on which modern applications are built. Although in my practice there has been no such thing as an interview ending after the first wrong answer, there are basics that need to be understood ahead of time.

A Junior developer is not tied to the programming language in any way, but a Senior can write more complex code. Then if you can solve these problems without any hints, most of the practical preparation for the Middle position is passed and you can focus on other topics during preparing for an interview.

1. Implement the method Array#map

A possible answer
class Array
  def map
    return unless block_given?

    result = []
    i = 0

    while self[i] do
      result << yield(self[i])
      i += 1
    end

    result
  end
end
Enter fullscreen mode Exit fullscreen mode

Checking the usage

[1,2,3,4].map { |x| x * 10 }
Enter fullscreen mode Exit fullscreen mode

2. Implement the method attr_accessor

A possible answer
module AttrAccessor
  def self.included(klass)
    klass.extend(ClassMethods)
  end

  module ClassMethods
    def custom_attr_accessor(*args)
      args.each do |arg|
        define_method(arg) do
          self.instance_variable_get("@#{arg}")
        end

        define_method("#{arg}=") do |value|
          self.instance_variable_set("@#{arg}", value)
        end
      end
    end
  end
end
Enter fullscreen mode Exit fullscreen mode

Checking the usage

class Car
  include AttrAccessor
  custom_attr_accessor :wheels_count, :driver_name
end

car = Car.new
car.wheels_count = 4
car.wheels_count

car.driver_name = 'Kevin'
car.driver_name
Enter fullscreen mode Exit fullscreen mode

3. Refactor the code by removing ifs

class HtmlFormatter
  def initialize(body)
    @body = body
  end

  def to_s
    "<body>#{@body}</body>"
  end
end

class JsonFormatter
  def initialize(body)
    @body = body
  end

  def to_s
    "{ body: #{@body} }"
  end
end

class Text
  def initialize(body)
    @body = body
  end

  def formatted(type=nil)
    if type == :json
      JsonFormatter.new(@body)
    elsif type == :html
      HtmlFormatter.new(@body)
    else
      raise 'an unknown format type'
    end
  end
end
Enter fullscreen mode Exit fullscreen mode

A possible answer
class Text
  def initialize(body, formatter)
    @body = body
    @formatter = formatter
  end

  def formatted
    @formatter.render(@body)
  end
end

class BaseFormatter
  def render(text)
    raise 'Not implemented :render method'
  end
end

class HtmlFormatter < BaseFormatter
  def render(text)
    "<body>#{text}</body>"
  end
end

class JsonFormatter < BaseFormatter
  def render(text)
    "{ body: #{text} }"
  end
end

class XmlFormatter < BaseFormatter
end
Enter fullscreen mode Exit fullscreen mode

Checking the usage

text = Text.new('Text', JsonFormatter.new)
puts text.formatted
Enter fullscreen mode Exit fullscreen mode

4. Write a code which help a command (1..10).select(&3) return [3, 6, 9]

A possible answer
class Fixnum
  def to_proc
    Proc.new { |item| item % self == 0 }
  end
end
Enter fullscreen mode Exit fullscreen mode

5. There is a code

class Post
  attr_reader :state, :title, :body

  def initialize(title, body)
    @title = title
    @body = body
    @state = :draft
  end

  def publish!
    @state = :published if @state == :draft
  end

  def delete!
    @state = :deleted if @state == :published
  end
end
Enter fullscreen mode Exit fullscreen mode

Extend the functionality of the class Post which allows changing any attribute of an instance of Post.
For example, Post.new.force_title('An awesome article') will be correct.

A possible answer
module Forceable
  def method_missing(method, *args, &block)
    if method =~ /force_(\w+)/ && previous_value = self.instance_variable_get("@#{$1}")
      self.instance_variable_set("@#{$1}", args.first)

      puts "Post changes #{$1} value from #{previous_value} to #{args.first}"
    else
      super
    end
  end
end

Post.include(Forceable)
Enter fullscreen mode Exit fullscreen mode

Checking the usage

post = Post.new('Title', 'Body')
post.force_state(:draft)
p post.state
Enter fullscreen mode Exit fullscreen mode

Top comments (0)