Перейти к основному содержимому

200 вопросов по Ruby

200 вопросов по Ruby

Основы Ruby

Вопрос

Что такое Ruby?

Ответ

Ruby — это динамический, интерпретируемый, объектно-ориентированный язык программирования общего назначения с автоматическим управлением памятью и гибкой системой метапрограммирования. Он поддерживает множественные парадигмы, включая процедурное, функциональное и объектно-ориентированное программирование.


Вопрос

Как запустить скрипт на Ruby из командной строки?

Ответ

Скрипт на Ruby запускается с помощью интерпретатора ruby, передавая имя файла в качестве аргумента:

ruby script.rb

Вопрос

Как вывести текст в консоль на Ruby?

Ответ

Для вывода текста в консоль используется метод puts:

puts "Привет, мир!"

Вопрос

Чем отличается puts от print?

Ответ

Метод puts добавляет символ новой строки после вывода, а print выводит строку без добавления перевода строки.


Вопрос

Как получить ввод от пользователя в Ruby?

Ответ

Ввод от пользователя получают с помощью метода gets:

name = gets.chomp

Метод chomp удаляет завершающий символ новой строки.


Вопрос

Какие есть типы комментариев в Ruby?

Ответ

В Ruby поддерживаются однострочные комментарии, начинающиеся с символа #, и многострочные комментарии, заключённые между =begin и =end.


Вопрос

Как определить переменную в Ruby?

Ответ

Переменную определяют путём присваивания значения без предварительного объявления типа:

x = 10

Вопрос

Какие виды переменных существуют в Ruby?

Ответ

В Ruby различают локальные переменные (name), глобальные переменные ($name), переменные экземпляра (@name), переменные класса (@@name) и константы (Name).


Вопрос

Что такое локальная переменная?

Ответ

Локальная переменная видна только в том блоке, методе или файле, где она определена, и начинается со строчной буквы или символа подчёркивания.


Вопрос

Что такое глобальная переменная?

Ответ

Глобальная переменная доступна из любого места программы и обозначается префиксом $.


Вопрос

Что такое переменная экземпляра?

Ответ

Переменная экземпляра принадлежит конкретному объекту, сохраняет своё значение между вызовами методов этого объекта и обозначается префиксом @.


Вопрос

Что такое переменная класса?

Ответ

Переменная класса принадлежит всему классу и разделяется между всеми его экземплярами. Она обозначается префиксом @@.


Вопрос

Что такое константа в Ruby?

Ответ

Константа — это переменная, имя которой начинается с заглавной буквы. Она предназначена для хранения значений, которые не должны изменяться, хотя Ruby допускает их переназначение с предупреждением.


Вопрос

Является ли Ruby статически или динамически типизированным языком?

Ответ

Ruby — динамически типизированный язык: тип переменной определяется во время выполнения, а не на этапе компиляции.


Вопрос

Как проверить тип объекта в Ruby?

Ответ

Тип объекта проверяют с помощью метода class:

x = 42
puts x.class # => Integer

Вопрос

Как проверить, принадлежит ли объект определённому классу?

Ответ

Принадлежность объекта классу проверяют с помощью метода is_a? или kind_of?:

42.is_a?(Integer)  # => true

Вопрос

Что такое nil в Ruby?

Ответ

nil — это специальный объект, представляющий отсутствие значения. Он является единственным экземпляром класса NilClass.


Вопрос

Как проверить, равен ли объект nil?

Ответ

Проверку на nil выполняют с помощью метода nil?:

value.nil?  # возвращает true, если value — nil

Вопрос

Какие значения считаются ложными в Ruby?

Ответ

В Ruby только два значения считаются ложными: false и nil. Все остальные значения, включая 0, пустую строку и пустой массив, считаются истинными.


Вопрос

Как работает оператор ||=?

Ответ

Оператор ||= присваивает значение переменной, только если она в данный момент равна nil или false:

x ||= 10  # эквивалентно x = x || 10

Вопрос

Как работает оператор &&=?

Ответ

Оператор &&= присваивает значение переменной, только если она в данный момент истинна:

x &&= 5  # эквивалентно x = x && 5

Вопрос

Что такое символ в Ruby?

Ответ

Символ — это неизменяемая строка-идентификатор, начинающаяся с двоеточия. Символы часто используются в качестве ключей в хэшах:

:name

Вопрос

Чем отличается символ от строки?

Ответ

Символ неизменяем и существует в единственном экземпляре в памяти на протяжении всей программы. Строка изменяема и каждый её экземпляр занимает отдельное место в памяти.


Вопрос

Как создать строку в Ruby?

Ответ

Строку создают с помощью двойных или одинарных кавычек:

str1 = "Привет"
str2 = 'Мир'

Вопрос

Как интерполировать переменную в строку?

Ответ

Интерполяцию выполняют внутри двойных кавычек с помощью конструкции #{}:

name = "Алиса"
greeting = "Здравствуй, #{name}!"

Вопрос

Как объединить две строки?

Ответ

Строки объединяют с помощью оператора + или метода <<:

"Hello" + " World"   # => "Hello World"
"Hello" << " World" # => "Hello World"

Вопрос

Как сравнить две строки?

Ответ

Строки сравнивают с помощью оператора == для проверки содержимого или метода eql? для строгого сравнения:

"abc" == "abc"  # => true

Вопрос

Что такое хэш в Ruby?

Ответ

Хэш — это коллекция пар «ключ–значение», где ключи обычно являются символами или строками:

person = { name: "Иван", age: 30 }

Вопрос

Как получить значение из хэша?

Ответ

Значение из хэша получают по ключу с помощью квадратных скобок:

person[:name]  # => "Иван"

Вопрос

Как задать значение по умолчанию для хэша?

Ответ

Значение по умолчанию задают при создании хэша:

h = Hash.new(0)
h[:missing] # => 0

Вопрос

Что такое массив в Ruby?

Ответ

Массив — это упорядоченная коллекция объектов, индексированных целыми числами, начиная с нуля:

colors = ["красный", "зелёный", "синий"]

Вопрос

Как получить элемент массива по индексу?

Ответ

Элемент массива получают с помощью квадратных скобок и индекса:

colors[0]  # => "красный"

Вопрос

Как добавить элемент в конец массива?

Ответ

Элемент добавляют в конец массива с помощью метода << или push:

colors << "жёлтый"

Вопрос

Как удалить последний элемент массива?

Ответ

Последний элемент удаляют с помощью метода pop, который также возвращает удалённое значение:

last = colors.pop

Вопрос

Как проверить, содержит ли массив определённый элемент?

Ответ

Проверку выполняют с помощью метода include?:

colors.include?("зелёный")  # => true

Вопрос

Что такое диапазон (Range) в Ruby?

Ответ

Диапазон представляет собой последовательность значений между двумя границами и создаётся с помощью .. (включительно) или ... (исключая правую границу):

(1..5).to_a   # => [1, 2, 3, 4, 5]
(1...5).to_a # => [1, 2, 3, 4]

Вопрос

Как определить метод в Ruby?

Ответ

Метод определяют с помощью ключевого слова def, за которым следует имя метода и, при необходимости, параметры:

def greet(name)
"Привет, #{name}!"
end

Вопрос

Как вернуть значение из метода?

Ответ

Метод возвращает значение последнего вычисленного выражения. Явный возврат выполняют с помощью ключевого слова return.


Вопрос

Можно ли определить метод с параметрами по умолчанию?

Ответ

Да, параметры по умолчанию задают прямо в сигнатуре метода:

def power(base, exponent = 2)
base ** exponent
end

Вопрос

Что такое ключевые аргументы (keyword arguments)?

Ответ

Ключевые аргументы — это именованные параметры, передаваемые в метод как хэш, но с более строгим синтаксисом:

def create_user(name:, email:)
"#{name} <#{email}>"
end

create_user(name: "Анна", email: "anna@example.com")

Вопрос

Как передать неограниченное число аргументов в метод?

Ответ

Для передачи произвольного числа аргументов используют оператор * (splat):

def sum(*numbers)
numbers.reduce(:+)
end

Вопрос

Что такое блок в Ruby?

Ответ

Блок — это фрагмент кода, который можно передать методу и выполнить внутри него. Блоки записывают с помощью фигурных скобок {} или ключевых слов do...end.


Вопрос

Как вызвать блок внутри метода?

Ответ

Блок вызывают с помощью ключевого слова yield:

def run_block
yield
end

run_block { puts "Выполнен блок" }

Вопрос

Что такое Proc?

Ответ

Proc — это объект, инкапсулирующий блок кода, который можно сохранить в переменную и вызвать позже с помощью метода call:

greet = Proc.new { puts "Привет!" }
greet.call

Вопрос

Что такое лямбда в Ruby?

Ответ

Лямбда — это особый вид Proc, создаваемый с помощью lambda или ->, который строже проверяет количество аргументов и обрабатывает return иначе:

square = ->(x) { x * x }
square.call(5) # => 25

Вопрос

Чем отличается лямбда от обычного Proc?

Ответ

Лямбда проверяет количество переданных аргументов и при вызове return возвращает управление из самой лямбды, а не из окружающего метода. Обычный Proc не проверяет аргументы и делает return из метода, в котором он вызван.


Вопрос

Что такое замыкание в Ruby?

Ответ

Замыкание — это блок, Proc или лямбда, который захватывает переменные из окружающей области видимости и сохраняет к ним доступ даже после выхода из этой области.


Вопрос

Как проверить, передан ли блок в метод?

Ответ

Проверку выполняют с помощью метода block_given?:

def optional_block
if block_given?
yield
else
puts "Блок не передан"
end
end

Вопрос

Что такое модуль в Ruby?

Ответ

Модуль — это коллекция методов и констант, которая не может быть инстанцирована и не поддерживает наследование, но может включаться в классы с помощью include или подключаться с помощью extend.


Вопрос

Для чего используют модули?

Ответ

Модули используют для группировки связанных методов, предотвращения коллизий имён и реализации примесей (mixins), чтобы добавлять функциональность нескольким классам.


Вопрос

Что такое класс в Ruby?

Ответ

Класс — это шаблон для создания объектов, определяющий их состояние (переменные экземпляра) и поведение (методы).


Вопрос

Как создать экземпляр класса?

Ответ

Экземпляр класса создают с помощью метода new:

obj = MyClass.new

Вопрос

Что такое конструктор в Ruby?

Ответ

Конструктор в Ruby — это метод initialize, который автоматически вызывается при создании нового объекта через new.


Вопрос

Можно ли перегружать методы в Ruby?

Ответ

Ruby не поддерживает классическую перегрузку методов по сигнатурам. Вместо этого используют параметры по умолчанию, splat-аргументы или проверку типов внутри метода.


Вопрос

Что такое наследование в Ruby?

Ответ

Наследование позволяет одному классу (подклассу) унаследовать методы и переменные другого класса (суперкласса). Ruby поддерживает одиночное наследование.


Вопрос

Как вызвать метод родительского класса?

Ответ

Метод родительского класса вызывают с помощью ключевого слова super:

def greet
super + ", рад вас видеть!"
end

Вопрос

Что такое self в Ruby?

Ответ

self — это ссылка на текущий объект или класс, в контексте которого выполняется код. Внутри метода экземпляра self указывает на объект, а внутри метода класса — на сам класс.


Вопрос

Как определить метод класса?

Ответ

Метод класса определяют с помощью self перед именем метода или внутри блока class << self:

def self.version
"1.0"
end

Вопрос

Что такое attr_reader, attr_writer, attr_accessor?

Ответ

Эти методы автоматически создают геттеры и сеттеры для переменных экземпляра:

  • attr_reader :name создаёт метод чтения name,
  • attr_writer :name создаёт метод записи name=,
  • attr_accessor :name создаёт оба метода.

Вопрос

Как защитить метод от внешнего вызова?

Ответ

Метод делают приватным с помощью private, что ограничивает его вызов только внутри текущего объекта:

private

def secret_method
"только внутри"
end

Вопрос

Что такое protected в Ruby?

Ответ

protected делает метод доступным только для вызова объектами того же класса или его подклассов.


Вопрос

Все ли в Ruby — объекты?

Ответ

Да, в Ruby всё является объектом: числа, строки, классы, даже nil и true.


Вопрос

Что такое класс Object?

Ответ

Object — это базовый класс, от которого наследуются все пользовательские классы по умолчанию. Он предоставляет основные методы, такие как inspect, to_s, class.


Вопрос

Что такое BasicObject?

Ответ

BasicObject — это минимальный корневой класс в иерархии Ruby, содержащий всего несколько методов. Он используется для создания изолированных объектов без стандартных методов Object.


Вопрос

Как узнать список методов объекта?

Ответ

Список методов объекта получают с помощью метода methods:

"строка".methods

Вопрос

Как проверить, отвечает ли объект на определённый метод?

Ответ

Проверку выполняют с помощью метода respond_to?:

obj.respond_to?(:to_s)  # => true, если метод to_s существует

Коллекции, перебор и стандартная библиотека

Вопрос

Как перебрать элементы массива в Ruby?

Ответ

Перебор элементов массива выполняют с помощью метода each:

[1, 2, 3].each { |x| puts x }

Вопрос

Чем отличается map от each?

Ответ

Метод each выполняет действие для каждого элемента и возвращает исходный объект. Метод map создаёт новый массив, применяя блок к каждому элементу и возвращая результаты.


Вопрос

Как отфильтровать элементы массива по условию?

Ответ

Фильтрацию выполняют с помощью метода select:

[1, 2, 3, 4].select { |x| x.even? }  # => [2, 4]

Вопрос

Как преобразовать каждый элемент массива и вернуть новый массив?

Ответ

Преобразование выполняют с помощью метода map (или его синонима collect):

[1, 2, 3].map { |x| x * 2 }  # => [2, 4, 6]

Вопрос

Как найти первый элемент, удовлетворяющий условию?

Ответ

Поиск первого подходящего элемента выполняют с помощью метода find (синоним detect):

[1, 2, 3].find { |x| x > 1 }  # => 2

Вопрос

Как проверить, все ли элементы удовлетворяют условию?

Ответ

Проверку выполняют с помощью метода all?:

[2, 4, 6].all?(&:even?)  # => true

Вопрос

Как проверить, существует ли хотя бы один элемент, удовлетворяющий условию?

Ответ

Проверку выполняют с помощью метода any?:

[1, 2, 3].any?(&:even?)  # => true

Вопрос

Как получить сумму всех элементов массива?

Ответ

Сумму получают с помощью метода sum:

[1, 2, 3].sum  # => 6

Вопрос

Как объединить все элементы массива в строку?

Ответ

Объединение выполняют с помощью метода join:

["a", "b", "c"].join(", ")  # => "a, b, c"

Вопрос

Как удалить дубликаты из массива?

Ответ

Удаление дубликатов выполняют с помощью метода uniq:

[1, 2, 2, 3].uniq  # => [1, 2, 3]

Вопрос

Как отсортировать массив?

Ответ

Сортировку выполняют с помощью метода sort:

[3, 1, 2].sort  # => [1, 2, 3]

Для кастомной сортировки передают блок:

["apple", "pie"].sort { |a, b| a.length <=> b.length }

Вопрос

Что делает оператор <=>?

Ответ

Оператор <=> (космический корабль) сравнивает два значения и возвращает -1, 0 или 1 в зависимости от того, меньше, равно или больше первое значение второго.


Вопрос

Как перевернуть массив?

Ответ

Переворот массива выполняют с помощью метода reverse:

[1, 2, 3].reverse  # => [3, 2, 1]

Вопрос

Как получить подмассив по индексам?

Ответ

Подмассив получают с помощью диапазона или двух аргументов:

arr = [0, 1, 2, 3]
arr[1..2] # => [1, 2]
arr[1, 2] # => [1, 2]

Вопрос

Как работает метод reduce?

Ответ

Метод reduce (синоним inject) последовательно применяет блок к аккумулятору и каждому элементу, возвращая одно значение:

[1, 2, 3].reduce(:+)  # => 6
[1, 2, 3].reduce(10) { |acc, x| acc + x } # => 16

Вопрос

Как создать хэш с ключами-символами?

Ответ

Хэш с символами в качестве ключей создают с синтаксисом key: value:

{ name: "Алиса", age: 30 }

Вопрос

Как перебрать пары ключ–значение в хэше?

Ответ

Перебор выполняют с помощью метода each:

{ a: 1, b: 2 }.each { |k, v| puts "#{k}: #{v}" }

Вопрос

Как преобразовать хэш в массив пар?

Ответ

Преобразование выполняют с помощью метода to_a:

{ a: 1, b: 2 }.to_a  # => [[:a, 1], [:b, 2]]

Вопрос

Как объединить два хэша?

Ответ

Объединение выполняют с помощью метода merge:

{ a: 1 }.merge(b: 2)  # => { a: 1, b: 2 }

Вопрос

Как удалить ключ из хэша?

Ответ

Удаление выполняют с помощью метода delete:

h = { a: 1, b: 2 }
h.delete(:a) # => 1, h становится { b: 2 }

Вопрос

Как проверить наличие ключа в хэше?

Ответ

Проверку выполняют с помощью метода key? (или has_key?):

{ a: 1 }.key?(:a)  # => true

Вопрос

Что такое Set в Ruby?

Ответ

Set — это коллекция уникальных элементов без порядка, реализованная в стандартной библиотеке (require 'set'). Она эффективна для операций типа объединения, пересечения и разности.


Вопрос

Как использовать регулярные выражения в Ruby?

Ответ

Регулярные выражения записывают между /.../ и применяют с помощью оператора =~ или методов строк:

"abc" =~ /b/  # => 1
"abc".match(/b/) # => #<MatchData "b">

Вопрос

Как извлечь совпадения из строки с помощью регулярного выражения?

Ответ

Извлечение выполняют с помощью метода scan:

"123 abc 456".scan(/\d+/)  # => ["123", "456"]

Вопрос

Как заменить подстроку по регулярному выражению?

Ответ

Замену выполняют с помощью метода gsub:

"hello world".gsub(/world/, "Ruby")  # => "hello Ruby"

Вопрос

Что возвращает метод match?

Ответ

Метод match возвращает объект MatchData, содержащий информацию о совпадении, или nil, если совпадения нет.


Вопрос

Как получить первую группу захвата из MatchData?

Ответ

Группы захвата доступны через индекс:

m = "2024-03-11".match(/(\d+)-(\d+)-(\d+)/)
m[1] # => "2024"

Вопрос

Как обработать исключение в Ruby?

Ответ

Обработку исключений выполняют с помощью конструкции begin ... rescue ... end:

begin
1 / 0
rescue ZeroDivisionError => e
puts "Ошибка: #{e.message}"
end

Вопрос

Какие базовые классы исключений есть в Ruby?

Ответ

Базовый класс — Exception. Большинство ошибок наследуются от StandardError, который является подклассом Exception.


Вопрос

Когда использовать rescue без указания класса?

Ответ

rescue без класса перехватывает только исключения, наследующиеся от StandardError. Это безопасно и рекомендуется в большинстве случаев.


Вопрос

Как выбросить исключение?

Ответ

Выброс исключения выполняют с помощью ключевого слова raise:

raise "Что-то пошло не так"
raise ArgumentError, "Неверный аргумент"

Вопрос

Что делает блок ensure?

Ответ

Блок ensure выполняется всегда — независимо от того, было ли исключение или нет. Он используется для освобождения ресурсов.


Вопрос

Как определить собственный класс исключения?

Ответ

Собственный класс исключения определяют как подкласс StandardError:

class MyError < StandardError; end
raise MyError, "Своя ошибка"

Вопрос

Что такое модуль Enumerable?

Ответ

Enumerable — это модуль, предоставляющий методы перебора (map, select, reduce и др.) для любого класса, реализующего метод each.


Вопрос

Как сделать свой класс совместимым с Enumerable?

Ответ

Нужно подключить модуль include Enumerable и реализовать метод each:

class Box
include Enumerable
def initialize(items); @items = items; end
def each(&block); @items.each(&block); end
end

Вопрос

Что делает метод zip?

Ответ

Метод zip объединяет элементы нескольких коллекций в массивы по позициям:

[1, 2].zip([3, 4])  # => [[1, 3], [2, 4]]

Вопрос

Как работает метод group_by?

Ответ

Метод group_by группирует элементы по значению, возвращаемому блоком:

[1, 2, 3, 4].group_by(&:even?)  # => { false => [1, 3], true => [2, 4] }

Вопрос

Как получить все возможные комбинации элементов массива?

Ответ

Комбинации получают с помощью метода combination:

[1, 2, 3].combination(2).to_a  # => [[1,2], [1,3], [2,3]]

Вопрос

Как получить все перестановки элементов массива?

Ответ

Перестановки получают с помощью метода permutation:

[1, 2].permutation.to_a  # => [[1,2], [2,1]]

Вопрос

Как работает метод partition?

Ответ

Метод partition разделяет коллекцию на две части: элементы, для которых блок возвращает true, и остальные:

[1, 2, 3].partition(&:even?)  # => [[2], [1, 3]]

Вопрос

Как проверить, пуст ли массив или хэш?

Ответ

Проверку выполняют с помощью метода empty?:

[].empty?      # => true
{}.empty? # => true

Вопрос

Как получить длину массива или хэша?

Ответ

Длину получают с помощью метода length или size:

[1, 2].length  # => 2
{ a: 1 }.size # => 1

Вопрос

Что делает метод compact?

Ответ

Метод compact удаляет все элементы, равные nil:

[1, nil, 2].compact  # => [1, 2]

Вопрос

Как применить блок к каждому элементу и «сплющить» результат?

Ответ

Это делает метод flat_map:

[[1, 2], [3, 4]].flat_map { |x| x.map { |y| y * 2 } }  # => [2, 4, 6, 8]

Вопрос

Как сравнить два хэша на равенство?

Ответ

Сравнение выполняют с помощью оператора ==, который проверяет равенство ключей и значений:

{ a: 1 } == { a: 1 }  # => true

Вопрос

Что такое Struct в Ruby?

Ответ

Struct — это лёгкий способ создать класс с предопределёнными атрибутами:

Point = Struct.new(:x, :y)
p = Point.new(1, 2)
p.x # => 1

Вопрос

Как импортировать модуль из стандартной библиотеки?

Ответ

Импорт выполняют с помощью require:

require 'json'
require 'date'

Вопрос

Как получить текущую дату и время?

Ответ

Текущую дату и время получают с помощью Time.now или DateTime.now:

Time.now

Вопрос

Как разобрать JSON-строку?

Ответ

Разбор выполняют с помощью JSON.parse:

require 'json'
JSON.parse('{"name":"Alice"}') # => { "name" => "Alice" }

Вопрос

Как сериализовать объект в JSON?

Ответ

Сериализацию выполняют с помощью to_json:

require 'json'
{ name: "Alice" }.to_json # => "{\"name\":\"Alice\"}"

Вопрос

Как прочитать содержимое файла?

Ответ

Чтение выполняют с помощью File.read:

content = File.read("file.txt")

Вопрос

Как записать строку в файл?

Ответ

Запись выполняют с помощью File.write:

File.write("file.txt", "Привет!")

Вопрос

Как выполнить команду оболочки из Ruby?

Ответ

Выполнение команды выполняют с помощью обратных кавычек или system:

output = `ls -l`
system("echo hello")

Вопрос

Что делает метод tap?

Ответ

Метод tap передаёт объект в блок и возвращает сам объект. Он полезен для отладки или промежуточных операций:

[1, 2, 3].tap { |x| puts x.inspect }.map(&:to_s)

Вопрос

Что такое method_missing?

Ответ

method_missing — это метод, вызываемый при попытке вызвать несуществующий метод. Его переопределяют для реализации динамического поведения.


Вопрос

Как проверить, определён ли метод в классе?

Ответ

Проверку выполняют с помощью defined? или method_defined?:

obj.respond_to?(:method_name)
String.method_defined?(:upcase)

Вопрос

Что такое send?

Ответ

Метод send вызывает метод по имени, переданному как символ или строка:

"hello".send(:upcase)  # => "HELLO"

Вопрос

Как получить список всех констант в модуле?

Ответ

Список констант получают с помощью constants:

Math.constants  # => [:PI, :E, ...]

Вопрос

Что делает instance_eval?

Ответ

instance_eval выполняет блок в контексте объекта, позволяя определять методы экземпляра или обращаться к приватным переменным.


Вопрос

Что делает class_eval?

Ответ

class_eval (синоним module_eval) выполняет блок в контексте класса, позволяя динамически определять методы класса или экземпляра.


Вопрос

Как клонировать объект в Ruby?

Ответ

Клонирование выполняют с помощью clone (поверхностная копия) или dup. clone сохраняет singleton-методы и frozen-статус, dup — нет.


Вопрос

Что такое frozen объект?

Ответ

Frozen-объект нельзя изменять. Попытка изменения вызывает FrozenError. Объект замораживают с помощью freeze.


Вопрос

Как проверить, заморожен ли объект?

Ответ

Проверку выполняют с помощью метода frozen?:

str = "hello".freeze
str.frozen? # => true

Вопрос

Что такое Symbol#to_proc?

Ответ

Symbol#to_proc позволяет кратко передавать метод как блок:

["a", "b"].map(&:upcase)  # эквивалентно map { |s| s.upcase }

Вопрос

Как работает оператор & перед аргументом?

Ответ

Оператор & преобразует объект в блок. Если передать &:method, Ruby вызовет to_proc у символа и использует результат как блок.


Вопрос

Что такое Enumerator?

Ответ

Enumerator — это объект, представляющий отложенный перебор. Он создаётся, когда each вызывается без блока:

enum = [1, 2].each
enum.next # => 1

Вопрос

Как создать бесконечную последовательность?

Ответ

Бесконечную последовательность создают с помощью Enumerator.new или loop:

inf = Enumerator.new { |y| i = 0; loop { y << i += 1 } }
inf.take(3) # => [1, 2, 3]

Вопрос

Как работает lazy в переборе?

Ответ

Метод lazy возвращает ленивый Enumerator, откладывающий вычисления до вызова force или потребления:

(1..Float::INFINITY).lazy.select(&:even?).first(3)  # => [2, 4, 6]

Метапрограммирование и объектная модель

Вопрос

Что такое метапрограммирование в Ruby?

Ответ

Метапрограммирование — это написание кода, который генерирует или изменяет другой код во время выполнения. Ruby предоставляет богатый набор инструментов для этого: define_method, method_missing, eval, class_eval, instance_eval и другие.


Вопрос

Как динамически определить метод экземпляра?

Ответ

Динамическое определение метода выполняют с помощью define_method внутри класса:

class Greeter
define_method :hello do |name|
"Привет, #{name}!"
end
end

Вопрос

Почему define_method предпочтительнее def в метапрограммировании?

Ответ

define_method принимает имя метода как символ или строку и тело как блок, что позволяет создавать методы с вычисляемыми именами и замыканиями. Конструкция def требует статического имени и не захватывает локальные переменные извне.


Вопрос

Как динамически определить метод класса?

Ответ

Метод класса определяют с помощью define_singleton_method или внутри class << self:

class MyClass
define_singleton_method :version do
"1.0"
end
end

Вопрос

Что делает method_missing?

Ответ

method_missing вызывается автоматически при попытке вызвать метод, который не определён в объекте или его цепочке наследования. Он принимает имя метода и аргументы.


Вопрос

Как правильно переопределить method_missing?

Ответ

При переопределении method_missing обязательно вызывают super в конце для обработки неизвестных вызовов и сохраняют сигнатуру (method_name, *args, &block):

def method_missing(name, *args, &block)
if name.to_s.start_with?("find_by_")
# обработка
else
super
end
end

Вопрос

Зачем вызывать super в method_missing?

Ответ

Вызов super гарантирует, что при обращении к действительно несуществующему методу будет выброшено стандартное исключение NoMethodError.


Вопрос

Как сделать метод, созданный через method_missing, видимым для respond_to??

Ответ

Нужно также переопределить метод respond_to_missing? и вернуть true для поддерживаемых динамических имён:

def respond_to_missing?(name, include_private = false)
name.to_s.start_with?("find_by_") || super
end

Вопрос

Что такое const_missing?

Ответ

const_missing — это аналог method_missing для констант. Он вызывается, когда запрашивается несуществующая константа в модуле или классе.


Вопрос

Как динамически создать класс?

Ответ

Класс создают с помощью Class.new, передавая опциональный родительский класс и блок для определения тела:

MyClass = Class.new do
def greet; "Привет"; end
end

Вопрос

Как динамически создать модуль?

Ответ

Модуль создают с помощью Module.new и блока:

MyMod = Module.new do
def hello; "Привет из модуля"; end
end

Вопрос

Что такое singleton-класс (eigenclass)?

Ответ

Singleton-класс — это скрытый класс, связанный с конкретным объектом, в котором хранятся методы, определённые только для этого объекта.


Вопрос

Как определить метод только для одного объекта?

Ответ

Метод определяют внутри блока class << object:

obj = Object.new
class << obj
def special_method
"Только у этого объекта"
end
end

Вопрос

Как проверить, есть ли у объекта singleton-класс?

Ответ

У каждого объекта есть singleton-класс. Его можно получить с помощью class << obj; self; end или метода singleton_class:

obj.singleton_class

Вопрос

Что делает instance_eval?

Ответ

instance_eval выполняет блок или строку в контексте получателя, где self указывает на сам объект. Он используется для определения методов экземпляра или доступа к приватным переменным.


Вопрос

Что делает class_eval?

Ответ

class_eval выполняет блок или строку в контексте класса, где self — это сам класс. Он позволяет динамически добавлять методы экземпляра или класса.


Вопрос

В чём разница между class_eval и instance_eval при работе с классом?

Ответ

При вызове на классе class_eval определяет методы экземпляра, а instance_eval — методы класса (потому что self внутри instance_eval — это сам класс как объект).


Вопрос

Как получить список всех методов, определённых непосредственно в классе (без наследуемых)?

Ответ

Список получают с помощью methods(false) или instance_methods(false):

String.instance_methods(false)

Вопрос

Как получить цепочку предков класса?

Ответ

Цепочку предков получают с помощью ancestors:

Array.ancestors  # => [Array, Enumerable, Object, Kernel, BasicObject]

Вопрос

Что такое included хук?

Ответ

included — это метод класса, который автоматически вызывается при включении модуля в класс с помощью include. Он позволяет выполнять дополнительную настройку.


Вопрос

Как реализовать хук included?

Ответ

Хук реализуют как метод класса внутри модуля:

module MyMixin
def self.included(base)
base.extend(ClassMethods)
end

module ClassMethods
def my_class_method; end
end
end

Вопрос

Что такое extended хук?

Ответ

extended — это метод класса, вызываемый при расширении объекта модулем с помощью extend. Он позволяет добавлять поведение в момент расширения.


Вопрос

Как реализовать хук extended?

Ответ

Реализация аналогична included:

module MyExt
def self.extended(obj)
puts "#{obj} был расширен"
end
end

Вопрос

Что такое method_added?

Ответ

method_added — это хук, вызываемый каждый раз при определении нового метода экземпляра в классе. Он принимает имя метода как символ.


Вопрос

Как использовать method_added?

Ответ

Его определяют как приватный метод класса:

class Tracer
def self.method_added(name)
puts "Определён метод: #{name}"
end
end

Вопрос

Какие ещё хуки существуют в Ruby?

Ответ

Существуют хуки:

  • singleton_method_added — при добавлении singleton-метода,
  • method_removed, method_undefined — при удалении или отмене метода,
  • inherited — при наследовании от класса.

Вопрос

Что делает хук inherited?

Ответ

inherited вызывается в родительском классе каждый раз, когда от него наследуется новый подкласс. Он принимает подкласс как аргумент.


Вопрос

Как реализовать простой DSL с помощью блока?

Ответ

DSL строят, передавая блок в метод и выполняя его в контексте специального объекта с помощью instance_eval:

def config(&block)
builder = ConfigBuilder.new
builder.instance_eval(&block)
builder
end

Вопрос

Что такое binding в Ruby?

Ответ

binding — это объект, представляющий текущую область видимости (локальные переменные, методы, self). Его можно передать в eval для выполнения кода в этом контексте.


Вопрос

Как работает eval?

Ответ

eval выполняет строку как код Ruby. При передаче binding он выполняется в указанной области видимости:

x = 10
eval("x + 5", binding) # => 15

Вопрос

В чём опасность eval?

Ответ

eval выполняет произвольный код, что создаёт риски безопасности при использовании с недоверенными входными данными. Его следует избегать в production-коде.


Вопрос

Что такое alias_method?

Ответ

alias_method создаёт псевдоним для существующего метода:

alias_method :new_name, :old_name

Вопрос

Чем alias_method отличается от alias?

Ответ

alias_method — это обычный метод, принимающий аргументы как символы или строки. alias — это ключевое слово языка, требующее статических имён и чувствительное к времени определения.


Вопрос

Как удалить метод из класса?

Ответ

Удаление выполняют с помощью remove_method (удаляет метод из текущего класса) или undef_method (делает метод недоступным, включая унаследованные):

remove_method :my_method

Вопрос

Что такое prepend?

Ответ

prepend вставляет модуль перед классом в цепочке предков, так что методы модуля вызываются до методов класса. Это позволяет безопасно переопределять поведение без super.


Вопрос

Как работает prepend в сравнении с include?

Ответ

При include модуль добавляется после класса в цепочке наследования. При prependдо. Это влияет на порядок вызова методов при переопределении.


Вопрос

Как проверить, включён ли модуль в класс?

Ответ

Проверку выполняют с помощью include?:

String.include?(Enumerable)  # => true

Вопрос

Как проверить, prepended ли модуль?

Ответ

Проверку выполняют через ancestors:

MyClass.ancestors.first == MyModule  # если prepended

Вопрос

Что такое refinements?

Ответ

Refinements — это механизм лексической области видимости для временного изменения поведения классов. Они активируются с помощью using и действуют только в текущем scope.


Вопрос

Как определить refinement?

Ответ

Refinement определяют с помощью Module#refine:

module StringRefinements
refine String do
def to_slug
downcase.gsub(/\s+/, '-')
end
end
end

using StringRefinements
"Hello World".to_slug # => "hello-world"

Вопрос

Почему refinements считаются безопасными?

Ответ

Refinements не изменяют глобальное состояние класса. Их эффект ограничен файлом или блоком, где вызван using.


Вопрос

Как работает delegate в Ruby?

Ответ

Делегирование — это передача вызова метода другому объекту. Вручную его реализуют через forwardable или явные методы:

require 'forwardable'
class Wrapper
extend Forwardable
def_delegator :@target, :length
end

Вопрос

Что такое Forwardable?

Ответ

Forwardable — это модуль из стандартной библиотеки, предоставляющий макросы def_delegator и def_delegators для быстрого делегирования методов.


Вопрос

Как реализовать паттерн «Builder» в Ruby?

Ответ

Паттерн Builder реализуют через класс с fluent-интерфейсом, где каждый метод возвращает self:

class QueryBuilder
def where(condition)
@conditions << condition
self
end

def build; @conditions.join(" AND "); end
end

Вопрос

Что такое «fluent interface»?

Ответ

Fluent interface — это стиль API, при котором методы возвращают self, позволяя цепочку вызовов:

obj.method1.method2.method3

Вопрос

Как реализовать паттерн «Decorator»?

Ответ

Декоратор оборачивает объект и делегирует ему вызовы, добавляя новое поведение:

class UpperCaseDecorator
def initialize(obj); @obj = obj; end
def content; @obj.content.upcase; end
end

Вопрос

Как реализовать паттерн «Null Object»?

Ответ

Null Object — это объект, реализующий тот же интерфейс, что и основной класс, но ничего не делающий:

class NullLogger
def info(*); end
def error(*); end
end

Вопрос

Что такое «duck typing» в Ruby?

Ответ

Duck typing — это подход, при котором тип объекта определяется не его классом, а наличием нужных методов: «Если ходит как утка и крякает как утка — это утка».


Вопрос

Как проверить наличие метода без вызова respond_to??

Ответ

Можно использовать конструкцию begin ... rescue NoMethodError, но это менее эффективно и не рекомендуется. respond_to? — стандартный способ.


Вопрос

Что такое «open classes» в Ruby?

Ответ

Open classes — это возможность повторного открытия любого класса (даже встроенных, таких как String или Integer) и добавления или изменения методов.


Вопрос

Какие риски связаны с open classes?

Ответ

Изменение глобального поведения встроенных классов может привести к коллизиям имён, неожиданному поведению в зависимостях и трудностям в отладке.


Вопрос

Как избежать коллизий при open classes?

Ответ

Используют уникальные имена методов, избегают изменения стандартных классов в библиотеках и предпочитают композицию или refinements.


Вопрос

Что такое BasicObject и зачем он нужен?

Ответ

BasicObject — это минимальный корневой класс без стандартных методов вроде puts, class, inspect. Он используется для создания изолированных объектов или DSL без загрязнения методами Object.


Вопрос

Как создать объект без методов Object?

Ответ

Наследуют от BasicObject:

class Clean < BasicObject
# почти пустой объект
end

Вопрос

Что такое «method object»?

Ответ

Method object — это объект класса Method, представляющий привязанный метод. Его получают с помощью method(:name):

m = "hello".method(:upcase)
m.call # => "HELLO"

Вопрос

Как вызвать метод по имени, хранящемуся в строке?

Ответ

Вызов выполняют с помощью send или public_send:

obj.send("method_name", arg1, arg2)

Вопрос

Чем public_send отличается от send?

Ответ

public_send вызывает только публичные методы и выбрасывает исключение при попытке вызвать приватный метод. send игнорирует уровень видимости.


Вопрос

Как получить исходный код метода?

Ответ

Исходный код метода получают с помощью source_location (путь и строка) или гема method_source:

method(:some_method).source_location

Вопрос

Что такое UnboundMethod?

Ответ

UnboundMethod — это метод, отсоединённый от объекта. Его можно привязать к другому совместимому объекту с помощью bind.


Вопрос

Как работает UnboundMethod#bind?

Ответ

bind привязывает несвязанный метод к объекту того же класса или его подкласса:

um = String.instance_method(:upcase)
um.bind("hello").call # => "HELLO"

Производительность, инструменты и лучшие практики

Вопрос

Как устроена система управления памятью в Ruby?

Ответ

Ruby использует автоматическое управление памятью на основе сборщика мусора (Garbage Collector, GC). Объекты, на которые нет ссылок, автоматически удаляются. Современные версии Ruby используют генерационную, компактизирующую и частично параллельную GC.


Вопрос

Что такое «младшее» и «старшее» поколения в GC Ruby?

Ответ

Объекты сначала размещаются в младшем поколении (minor heap). Если они выживают несколько циклов сборки, они перемещаются в старшее поколение (major heap). Сборка младшего поколения происходит чаще и быстрее.


Вопрос

Как уменьшить давление на GC?

Ответ

Снижение давления достигается за счёт повторного использования объектов, избегания создания временных объектов в горячих циклах и использования frozen-строк (# frozen_string_literal: true).


Вопрос

Что делает магический комментарий # frozen_string_literal: true?

Ответ

Этот комментарий указывает интерпретатору создавать все строковые литералы в файле как замороженные (frozen), что снижает потребление памяти и предотвращает случайные изменения.


Вопрос

Как профилировать производительность Ruby-кода?

Ответ

Профилирование выполняют с помощью гемов benchmark, ruby-prof, stackprof или встроенных средств:

require 'benchmark'
Benchmark.bm { |x| x.report { some_code } }

Вопрос

Что такое «горячий путь» (hot path)?

Ответ

Горячий путь — это участок кода, который выполняется наиболее часто. Оптимизация именно этого участка даёт наибольший прирост производительности.


Вопрос

Поддерживает ли Ruby настоящие параллельные потоки?

Ответ

В MRI (официальной реализации Ruby) действует Global Interpreter Lock (GIL), который позволяет выполнять только один поток Ruby-кода одновременно. Параллельность возможна только при операциях ввода-вывода или в нативных расширениях.


Вопрос

Что такое GIL?

Ответ

GIL (Global Interpreter Lock) — это мьютекс, защищающий внутреннее состояние интерпретатора Ruby. Он гарантирует, что только один поток выполняет Ruby-инструкции в любой момент времени.


Вопрос

Как запустить код в отдельном потоке?

Ответ

Поток создают с помощью Thread.new:

t = Thread.new { sleep 1; puts "Готово" }
t.join

Вопрос

Как обмениваться данными между потоками?

Ответ

Обмен данными осуществляют через общие переменные с синхронизацией с помощью Mutex:

mutex = Mutex.new
value = 0
threads = 2.times.map do
Thread.new do
mutex.synchronize { value += 1 }
end
end
threads.each(&:join)

Вопрос

Что такое Queue в Ruby?

Ответ

Queue — это потокобезопасная очередь из стандартной библиотеки (require 'thread'), используемая для передачи данных между потоками.


Вопрос

Как дождаться завершения всех потоков?

Ответ

Для каждого потока вызывают метод join:

threads = [Thread.new { ... }, Thread.new { ... }]
threads.each(&:join)

Вопрос

Что такое «fiber» в Ruby?

Ответ

Fiber — это лёгковесная кооперативная единица выполнения. В отличие от потоков, fiber переключаются вручную с помощью resume и yield.


Вопрос

Как использовать fiber?

Ответ

Fiber создаётся и управляется явно:

f = Fiber.new do
Fiber.yield 1
Fiber.yield 2
end
f.resume # => 1
f.resume # => 2

Вопрос

Для чего используют fiber?

Ответ

Fiber применяют для реализации асинхронных библиотек, генераторов, корутин и легковесного concurrency без накладных расходов потоков.


Вопрос

Как писать тесты на Ruby?

Ответ

Тесты пишут с помощью фреймворков Minitest (входит в стандартную библиотеку) или RSpec (популярный сторонний гем).


Вопрос

Как выглядит простой тест на Minitest?

Ответ

require 'minitest/autorun'

class TestMath < Minitest::Test
def test_addition
assert_equal 4, 2 + 2
end
end

Вопрос

Как выглядит простой тест на RSpec?

Ответ

RSpec.describe Calculator do
it "adds two numbers" do
expect(Calculator.add(2, 2)).to eq(4)
end
end

Вопрос

Что такое describe, it, expect в RSpec?

Ответ

describe группирует тесты по контексту, it описывает отдельное поведение, expect задаёт утверждение (assertion) с использованием matcher’ов.


Вопрос

Как мокать зависимости в тестах?

Ответ

В RSpec используют allow или instance_double. В Minitest — гем minitest/mock:

# RSpec
allow(api).to receive(:fetch).and_return("data")

Вопрос

Что такое TDD?

Ответ

TDD (Test-Driven Development) — это подход, при котором сначала пишут тест, затем минимальную реализацию, проходящую тест, и далее рефакторинг.


Вопрос

Что такое BDD?

Ответ

BDD (Behavior-Driven Development) — это расширение TDD, ориентированное на описание поведения системы на языке, понятном бизнесу (например, через describe и it в RSpec).


Вопрос

Что делает Bundler?

Ответ

Bundler управляет зависимостями проекта, устанавливая точные версии гемов, указанных в Gemfile, и обеспечивая воспроизводимость окружения.


Вопрос

Как добавить гем в проект?

Ответ

Гем добавляют в Gemfile:

gem "rspec"

Затем выполняют bundle install.


Вопрос

Что такое Gemfile.lock?

Ответ

Gemfile.lock фиксирует точные версии всех установленных гемов и их зависимостей, гарантируя одинаковое окружение у всех разработчиков.


Вопрос

Что такое Rake?

Ответ

Rake — это система задач на Ruby, аналог Make. Она используется для автоматизации: запуска тестов, миграций, очистки и других рутинных операций.


Вопрос

Как определить задачу в Rake?

Ответ

Задачу определяют в Rakefile:

task :hello do
puts "Привет из Rake!"
end

Запуск: rake hello.


Вопрос

Что такое RuboCop?

Ответ

RuboCop — это инструмент статического анализа кода, проверяющий соответствие стилю Ruby Style Guide и выявляющий потенциальные ошибки.


Вопрос

Как настроить RuboCop?

Ответ

Настройку выполняют через файл .rubocop.yml, где можно включать/отключать правила и задавать параметры:

Style/StringLiterals:
Enabled: true
EnforcedStyle: double_quotes

Вопрос

Что такое require и load?

Ответ

require загружает файл только один раз, даже при повторных вызовах. load загружает файл каждый раз заново.


Вопрос

Когда использовать require_relative?

Ответ

require_relative используется для загрузки файлов относительно текущего файла, без указания полного пути:

require_relative "lib/helper"

Вопрос

Что такое «идемпотентность» в контексте требований к коду?

Ответ

Идемпотентная операция даёт один и тот же результат при многократном выполнении. Например, require идемпотентен, а load — нет.


Вопрос

Как избежать циклических зависимостей при require?

Ответ

Циклические зависимости избегают путём рефакторинга: вынесения общего кода в отдельный модуль, использования ленивой загрузки или пересмотра архитектуры.


Вопрос

Что такое «convention over configuration»?

Ответ

Это принцип, согласно которому фреймворк использует разумные соглашения по умолчанию, избавляя разработчика от необходимости конфигурировать всё вручную (например, в Rails: имя таблицы — множественное от имени модели).


Вопрос

Почему важно писать читаемый код на Ruby?

Ответ

Ruby спроектирован так, чтобы код был близок к естественному языку. Читаемость повышает поддерживаемость, снижает количество ошибок и упрощает командную работу.


Вопрос

Какие принципы SOLID применимы в Ruby?

Ответ

Все пять принципов SOLID применимы:

  • Single Responsibility
  • Open/Closed
  • Liskov Substitution
  • Interface Segregation
  • Dependency Inversion
    Они реализуются через модули, наследование, делегирование и dependency injection.

Вопрос

Что такое dependency injection в Ruby?

Ответ

Dependency injection — это передача зависимостей (объектов или сервисов) в класс извне, а не создание их внутри. Это упрощает тестирование и гибкость:

class Service
def initialize(logger); @logger = logger; end
end

Вопрос

Как организовать большую кодовую базу на Ruby без фреймворка?

Ответ

Используют модульную структуру, соглашения об именовании файлов, autoload или явные require, выделяют слои (domain, infrastructure, application) и следуют принципам чистой архитектуры.


Вопрос

Что такое autoload?

Ответ

autoload регистрирует константу и путь к файлу, который будет загружен автоматически при первом обращении к этой константе:

autoload :User, "models/user"

Вопрос

Почему autoload deprecated в Ruby 3?

Ответ

autoload не является потокобезопасным и может вызывать race conditions. Вместо него рекомендуют использовать явные require или системы загрузки вроде Zeitwerk (используется в Rails).


Вопрос

Что такое Zeitwerk?

Ответ

Zeitwerk — это современный механизм автоматической загрузки констант для Ruby, потокобезопасный и совместимый с соглашениями об именовании файлов и классов.


Вопрос

Как обрабатывать ошибки в продакшене?

Ответ

Ошибки логируют с контекстом, избегают раскрытия внутренних деталей пользователю, используют мониторинг (Sentry, Rollbar) и обеспечивают graceful degradation.


Вопрос

Что такое «defensive programming»?

Ответ

Defensive programming — это практика написания кода, устойчивого к некорректным входным данным: проверка аргументов, использование freeze, избегание мутаций.


Вопрос

Как сделать хэш неизменяемым?

Ответ

Хэш делают неизменяемым с помощью freeze:

config = { host: "localhost" }.freeze

Вопрос

Что такое «value object»?

Ответ

Value object — это неизменяемый объект, равенство которого определяется значениями его атрибутов, а не идентичностью. Пример: Date, Money.


Вопрос

Как сравнить два объекта по содержимому?

Ответ

Переопределяют метод ==, сравнивая значимые атрибуты:

def ==(other)
other.is_a?(self.class) && name == other.name
end

Вопрос

Нужно ли переопределять eql? и hash?

Ответ

Если объект используется как ключ в хэше, нужно переопределить eql? и hash, чтобы равные объекты имели одинаковый хэш-код.


Вопрос

Как работает хэширование в Ruby?

Ответ

Каждый объект имеет метод hash, возвращающий целое число. Хэш-таблицы (например, Hash) используют это значение для быстрого поиска. Равные объекты должны иметь одинаковый hash.


Вопрос

Что такое «semantic versioning»?

Ответ

Semantic Versioning (SemVer) — это соглашение о нумерации версий: MAJOR.MINOR.PATCH. MAJOR — обратно несовместимые изменения, MINOR — обратно совместимые новые функции, PATCH — исправления.


Вопрос

Как публиковать свой гем?

Ответ

Гем публикуют через gem push my_gem-1.0.0.gem после сборки с помощью gem build gemspec_file.gemspec.


Вопрос

Что такое .gemspec?

Ответ

.gemspec — это файл, описывающий метаданные гема: имя, версию, зависимости, файлы и автора.


Вопрос

Как документировать Ruby-код?

Ответ

Документацию пишут в виде комментариев над методами и классами, используя формат YARD или RDoc. Генераторы создают HTML-документацию из этих комментариев.


Вопрос

Что такое YARD?

Ответ

YARD — это система документирования Ruby-кода, поддерживающая теги (@param, @return), типы и генерацию красивой HTML-документации.


Вопрос

Как обеспечить обратную совместимость при изменении API?

Ответ

Сохраняют старые методы как deprecated, добавляют новые, логируют предупреждения и удаляют старое только в следующей мажорной версии.


Вопрос

Что такое «deprecation warning»?

Ответ

Deprecation warning — это предупреждение, информирующее, что метод или функция устарели и будут удалены в будущем.


Вопрос

Как писать код, устойчивый к изменениям?

Ответ

Следуют принципам: маленькие методы,单一 ответственность, избегание жёсткой связности, использование интерфейсов и покрытие тестами.


Вопрос

Почему Ruby популярен для веб-разработки?

Ответ

Ruby популярен благодаря фреймворку Ruby on Rails, который предлагает высокую продуктивность, соглашения вместо конфигурации, богатую экосистему и выразительный синтаксис.


Вопрос

Какие альтернативные реализации Ruby существуют?

Ответ

Существуют JRuby (на JVM), TruffleRuby (на GraalVM), Rubinius (на LLVM). Они предлагают лучшую производительность или интеграцию с другими платформами.


Вопрос

Чем JRuby отличается от MRI?

Ответ

JRuby компилируется в байт-код JVM, поддерживает настоящую параллельность потоков, интегрируется с Java-библиотеками, но может иметь другие нюансы GC и совместимости.


Вопрос

Что такое «RubyKaigi»?

Ответ

RubyKaigi — это ежегодная международная конференция разработчиков Ruby, где обсуждают будущее языка, делятся опытом и представляют новые инструменты.


Вопрос

Как участвовать в развитии Ruby?

Ответ

Можно отправлять issue и pull request в репозиторий ruby/ruby на GitHub, участвовать в обсуждениях RFC, тестировать preview-версии и писать документацию.


Вопрос

Что нового в Ruby 3?

Ответ

Ruby 3 представил: Ractors (для параллелизма), Fibers scheduler (для асинхронности), TypeProf (для типизации), улучшенную производительность (3x цель Matz), pattern matching и многое другое.


Вопрос

Что такое Ractor?

Ответ

Ractor — это новый уровень изоляции в Ruby 3, позволяющий безопасный параллелизм без shared memory. Ractors обмениваются данными только через сообщения.


Вопрос

Что такое pattern matching в Ruby?

Ответ

Pattern matching — это конструкция case ... in, позволяющая деконструировать сложные структуры данных:

case data
in { name:, age: Integer => a } if a > 18
puts "#{name} взрослый"
end

Вопрос

Как проверить тип аргумента в методе?

Ответ

Проверку выполняют с помощью is_a? или сторонних решений для типизации (например, Sorbet):

raise TypeError unless value.is_a?(String)

Вопрос

Что такое Sorbet?

Ответ

Sorbet — это статический анализатор типов для Ruby, позволяющий добавлять аннотации типов и находить ошибки до выполнения.


Вопрос

Как начать использовать Sorbet?

Ответ

Устанавливают гем sorbet, запускают srb init, добавляют аннотации sig и проверяют типы с помощью srb tc.


Вопрос

Что такое «duck typing» и как он соотносится со статической типизацией?

Ответ

Duck typing полагается на наличие методов, а не на объявленный тип. Статическая типизация (например, в Sorbet) добавляет проверки на этапе разработки, не нарушая динамическую природу Ruby.


Вопрос

Как выбрать между Ruby и другими языками для проекта?

Ответ

Ruby выбирают для быстрой разработки MVP, стартапов, прототипирования и проектов с акцентом на developer experience. Для высоконагруженных систем могут предпочесть Go, Rust или Java.


Вопрос

Какие книги рекомендуются для изучения Ruby?

Ответ

Классические книги:

  • «The Well-Grounded Rubyist» (David A. Black)
  • «Eloquent Ruby» (Russ Olsen)
  • «Metaprogramming Ruby» (Paolo Perrotta)

Вопрос

Как готовиться к собеседованию по Ruby?

Ответ

Изучают основы языка, коллекции, блоки, объектную модель, метапрограммирование, стандартную библиотеку, пишут код, решают задачи, разбирают исходники популярных гемов и практикуют объяснение решений вслух.


Вопрос

Что спрашивают на senior-собеседованиях по Ruby?

Ответ

Спрашивают про архитектуру приложений, управление зависимостями, производительность, GC, конкурентность, опыт работы с legacy, подход к рефакторингу, стратегии тестирования и участие в open source.


Вопрос

Как показать глубокое понимание Ruby на собеседовании?

Ответ

Объясняют не только «как», но и «почему»: как устроен lookup методов, как работает GC, почему GIL существует, как реализованы хэши, как работает method_missing и как его безопасно использовать.


Вопрос

Что делать, если не знаешь ответа на вопрос?

Ответ

Честно сказать, что не знаешь, но предложить рассуждать вслух, привести аналогии из смежных областей или описать, как бы искал решение.


Вопрос

Как оценить качество Ruby-кода?

Ответ

Качество оценивают по читаемости, тестируемости, отсутствию дублирования, соблюдению принципов SOLID, покрытию тестами, соответствию стилю и отсутствию code smells.


Вопрос

Что такое «code smell»?

Ответ

Code smell — это признак потенциальной проблемы в коде: длинные методы, большое число параметров, дублирование, feature envy, god object и другие.


Вопрос

Как рефакторить legacy-код на Ruby?

Ответ

Сначала покрывают существующее поведение тестами (characterization tests), затем постепенно выделяют модули, упрощают методы, удаляют мутации и вводят dependency injection.


Вопрос

Почему важно писать тесты для метапрограммирования?

Ответ

Метапрограммирование скрывает логику за динамическими вызовами. Тесты гарантируют, что поведение соответствует ожиданиям и не нарушается при изменениях.


Вопрос

Как поддерживать мотивацию при изучении Ruby?

Ответ

Строят небольшие проекты, участвуют в open source, читают исходный код гемов, общаются с сообществом, ставят конкретные цели и отмечают прогресс.