Пишу данный пост чтобы избавиться от давно мучавшей проблемы: «Почему в Rails используется наследование, а не миксины». Вообще, задумался об этом давно, точнее мне об этом рассказал Дейв Томас в своем видеоролике(хз как это назвать, может быть скринкаст).
Читать далее(Нажал на кнопку хабракат, надеюсь так он у вас и работает.)
Чтобы было понятнее, я сделал несколько скриншотов.
Для начала объясню, зачем вообще нужны наследование и прочие объектно-ориентированые штуки.
Рис. 1 Тру говнокод
Как видно(если кликнуть на картинку), код дублируется. А зачем?
Warning!!!
Внимательно посмотрите, на методы find! Разве они должны принадлежать объекту? НЕТ! Поэтому быстро переписываем чтобы дальше было ясно, что нам надо разделять методы объектов и класса.
Рис.2 Чуть-чуть пофиксеный говнокод
Ну от одной ошибки уже избавились.(Да, там и сейчас полная фигня. Возвращаются строки и прочий треш, но давайте сделаем вид, что так и надо. Главное что видим селект например. Короче делаем вид, что всё работает)
Итак, приступаем к написанию родительского класса. Я назвал его ActiveRecord. Да, именно так.
Рис. 3 Родительский класс.
Немного руби магии и наш говнокод всё-ещё работает!
Мы вынесли весь ДБ треш из классов и теперь можем спокойно создавать и выбирать объекты из бд(^.^ да, я немного преувеличил). И никакого кода внутри классов User и Comment! О нас позаботился родительский класс.
Но сколько может быть родительских классов? Почему мы можем наследовать только от одного класса. Может я хочу наследовать деньги от Рокфеллеров, а внешность от парочки Питт-Джоли. Хм, сейчас мы сделаем первый шаг навстречу светлому будущему!!!
Рис. 4 Итак, миксины!!
Уже лучше. Немного руби магии и мы можем использовать методы уровня объекта и уровня класса. Только неохото писать везде extend=( Что ж, и тут мы можем немного облегчить себе жизнь и не запоминать, что надо include, а что extend.
Рис.5 Больше никто не забудет написать extend.
ОО, наш код стал идеальным(хи хи хи)
И пара скринов, зачем мы писали всё предыдущее надругательство над Rails
Допустим, у нас есть классы юзер и коммент. Нам надо их хранить и получать их БД. Благодаря модулю Persistable, эта фигулина у нас работает. Теперь представим, что у нас добавился класс Person(да, я хочу чтобы он не хранился в БД. Такой дурачок, который работает только чтобы показать свой возраст и т.п.). Допустим, он чем-то схож с User. Вычленяем это в Humanized и вуаля!
Рис 6 (1,2) }{уманайзед!
Хорошо, Вы скажите, а зачем вообще всё это? Да по — любому Person хранится в БД. Значит он с User один и тот же класс, только у User есть дата регистрации и пароль. Делаем суперкласс HumanInDB и все! Но тогда у нас отлетает Comments же! Ладно, скажете Вы, пусть так. Делаем суперкласс StuffFromDB, от него HumanInDB и Comments наследуем например.
ОК, Вы меня победили. FUUUUCCKKKK!!!