Прошу объяснить, как работает self и protected в Ruby?
Public - должны использоваться очень аккуратно. Чем меньше - тем лучше. Это внешнее API для других классов, которые будут его использовать. А чем меньше можно узнать, тем быстрее это можно выучить и запомнить, тем меньше ошибок сделать.Protected - это те методы, которые доступны потомкам (классам, что наследуют), но не доступны внешним классам. Грубо говоря, удобно, когда вы знаете, что от класса А будут наследовать много-много разных классов, и у этих классов будет один (или много, не важно) общий метод. Который, однако, совершенно не нужен внешним классам. Если бы не было протектеда, было бы 2 пути - сделать метод, который должен быть у всех потомков - публичным. Это плохо, потому что это лишняя информация для внешних классов. Или же - дублировать одинаковые методы в каждом классе потомке. Это плохо, потому что не DRY.Private - это те методы, который доступны только классу. То есть, грубо говоря, пользоваться ими вы можете только в том же файле, где идет определение класса. Например, удобно ими пользоваться для рефакторинга. Представим, что есть публичный метод, который уже много лет используют 100 разных, неизвестных классов. Но в этом методе - 500 строк. Менять метод нельзя, поэтому вы превращаете его в 10 строк-вызовов приватных методов.
Лучше всего это усвоить, создав разные вариации и попробовав повызывать разные методы. 2 важных вещи, которые нужно помнить в Ruby: 
1) Разные ключевые слова для методов класса и экземпляра (private, private_class_method)
2) Если тестируете поведение в консоли с использованием #send, то поведение будет не ООП-шное - #send игнорирует видимость методов
С self все проще. По умолчанию, всегда self подставляется. Метод вызывается сначала для текущего объекта - потом смотрится наличие методов в предке и т.д. и т.д. до объекта Object. Зачем иногда явно пишут self ? Потому что в руби можно создавать методы вида def method=() end; и использовать их с пробелом: method = 2. Для этого, что бы дать понять, что используется именно метод, а не определяется локальная переменная, иногда прибегают к полной записи.
P.S. Если что-то действительно не понятно даже здесь - берите любую книгу по ООП или википедию и пробуйте все в консоли на любом языке программирования, пока не уловите суть.
Эх батенька. Это вам основы ООП нужно изучать. Всякие там инкапсуляции, абстракции, полиморфизмы.
Если вам тут объяснят, то вам это ничем не поможет. Вы основ не знаете.