Andrew Molchanov
Posted on May 23, 2022
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
Checking the usageA 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
[1,2,3,4].map { |x| x * 10 }
2. Implement the method attr_accessor
Checking the usageA 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
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
3. Refactor the code by removing if
s
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
Checking the usageA 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
text = Text.new('Text', JsonFormatter.new)
puts text.formatted
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
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
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.
Checking the usageA 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)
post = Post.new('Title', 'Body')
post.force_state(:draft)
p post.state
Posted on May 23, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.