Несколько задачек по основам Ruby и часто используемым функциям языка для собеседования на позицию middle разработчика.
7К открытий9К показов
Андрей Молчанов
Senior Software Engineer в Uscreen
Позиции Junior, Middle и Senior в СНГ различаются не только от компаний к компаниям, но и в принципе отсутствуют в некоторых странах. Для проведения интервью у кого-то есть заранее подготовленный набор тестовых заданий, кто-то предпочитает беседу за жизнь вперемешку с конкретными техническими вопросами. Есть компании, которым важны преимущественно soft skills. И все-таки выявить подходящего кандидата — дорогостоящий процесс.
После прохождения интервью во множество компаний есть понимание, что кандидат должен знать и уметь применять основные принципы, на которых строятся современные приложения. И хотя в моей практике не было такого, чтобы интервью закончилось после первого неправильного ответа или вопроса, — есть основы, в которых надо разобраться заранее.
В этом материале создана подборка по основам Ruby, часто используемым функциям языка. И если Junior разработчик никак не привязан к языку программирования, а Senior может писать более сложный код, то если вы сможете решить эти задачи без подсказок — бо́льшая часть практической подготовки на позицию Middle пройдена и можно сфокусироваться на других темах при подготовке к собеседованию.
Реализуйте метод Array#map
Вариант ответа
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 }
Реализуйте метод attr_accessor
Вариант ответа
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
p car.wheels_count
car.driver_name = 'Kevin'
p car.driver_name
Перепишите код без использования if
class HtmlFormatter
def initialize(body)
@body = body
end
def to_s
"#{@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
Проверка использования:
text = Text.new('New text')
puts text.formatted(:json)
Вариант ответа
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)
"#{text}"
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
Напишите код, чтобы строка (1..10).select(&3) возвращала результат [3, 6, 9]
Вариант ответа
class Fixnum
def to_proc
Proc.new { |item| item % self == 0 }
end
end
Добавьте функциональность объекта post, изменяющую значение любого параметра объекта на требуемое и логирующую это изменение
Класс Post:
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
Вариант ответа
require 'logger'
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.publish!
p post.state
post.publish!
p post.state
post.force_state(:draft)
p post.state