Дмитрий, всё дело в сложном if-е:
Вы написали вот так:
if @letters.include? bukva ||
(bukva == "е" && @letters.include?("ё")) ||
(bukva == "ё" && @letters.include?("е")) ||
(bukva == "и" && @letters.include?("й")) ||
(bukva == "й" && @letters.include?("и"))
и не забрали аргумент метода include? в скобки, надеясь, что Ruby сам догадается, что да как. Но Ruby догадался неверно и сперва вычислил сложное выражение:
bukva ||
(bukva == "е" && @letters.include?("ё")) ||
(bukva == "ё" && @letters.include?("е")) ||
(bukva == "и" && @letters.include?("й")) ||
(bukva == "й" && @letters.include?("и"))
... и получилось true. А потом передал передал его методу include? в качестве параметра. Так как в массиве букв нет объекта true, этот метод вернул false и мы сочли букву за ошибку.
С и и й будет, кстати точно то же самое.
Мораль: аккуратнее с опусканием скобок. Я бы предложил такое правило — пока вы на 100% не уверены, как интерпретатор воспримет ваш код, не ленитесь лишний раз поставить скобки.