Появились вопросы - откуда начать изучение Ruby и Rails. Поскольку тема занятная, пишу отдельным постом. В плане литературы - начать с PickAxe (русского перевода нет и не будет), продолжить на Ruby Hacking Guide и попытаться добыть The Ruby Way. После (и только после!) того как базовые идиомы Ruby освоены (заняло у меня недели две) можно приступать к Rails. Для этого есть Agile Web Development with Rails - книжка очень неплохая, но к сожалению (на мой взгляд) она не рассказывает об идеологии Rails (а без ее понимания многие решения будут поначалу казаться абсурдными). Завершить пир духа можно свежевышедшей Enterprise Integration With Rails.

Попутно - нужно освежить знания объектно-ориентированного программирования (особенно если опыта такового раньше не было) - потому что без него на Ruby у вас будет получаться плохая пародия на Perl. Ничего, если PHP вы знаете плохо - но если вам не ясны базовые понятия ООП или вы сомневаетесь в том что огромное количество народу их зачем-то придумывало, много пользы вам извлечь из занятий Ruby будет сложновато. Тем более если вы отвергаете ООП как практику в целом - это модно в русском PHP-сообществе (хотя зачем вам тогда Ruby - пишите сразу на ассемблере).

Technorati Tags: ,

Из русских ресурсов тоже есть что почерпнуть. Несколько интересных людей дают Ruby как вводный язык на кафедрах вычислительной техники - их материалы открыто доступны и весьма полезны (особенно при первых шагах). Все курсовые материалы Рубиновича, например, рекомендуются к освоению - равно как и регистрация на единственном (но абсолютно воспитанном) Ruby-форуме. К великому сожалению, в отличие от упомянутых мною выше книг эти учебные материалы не затрагивают идеологию Ruby - а это тот самый “дизайн”, без чувства которого количество удовольствия радикально сокращается. Попутно команда этого форума поддерживает целый русскоязычный сайт, посвященный Ruby.

А что такое дизайн?

Один господин вот жалуется, что ему не нравятся идентификаторы $, @ и пр. Ответ прост - благодаря идентификатору @ никогда не возникнет сомнений, обращаемся мы к свойству объекта или к методу. Идентификатор @@ позволяет избежать придумывания целой батареи синтаксиса доступа к статическим свойствам класса. Главная же претензия -наличие def и end объясняется крайне просто. Ни один человек, который пишет скрипты на рубине не будет выбирать из 3 религиозных вариантов расстановки фигурных скобок вокруг тела функции - потому что нету фигурных скобок. Таким образом весь код с точки зрения дизайна языка теряет еще одну глупость которую можно сознательно сделать отличной по стилю от кода чужого - а следовательно – делает ваш код более читаемым для коллег. Или - что принято что все методы пишутся в змеиной_нотации, а все классы в ЗаглавныхБезПробелов. Это - большой подарок, потому что ни у кого не возникает после этого идеи составлять 169 code style guide а все интуитивно помнят, как код должен быть оформлен. Я знаю что ни один рубинист в здравом уме не станет именовать методы и переменные через studlyCaps когда 100 процентов его соседей делают это как положено. Вы говорите - “зачем это в языке?”. А затем - чтоб порядок был. Иначе базар (как мы уже неоднократно имели убедиться). При начале работы с Рубином остается только один выбор – принять эти конвенции как свои собственные и следовать им беспрекословно. And that’s a GoodThing™. Да, а идентификатор $ в нормальной Ruby-программе не встречается, поскольку засорять своими переменными глобальное пространство имен как-то моветон, да-с. Не говоря уж о том, что все метод - то есть есть и перегрузка операторов(у всего), и подстановка методов at runtime. Например:

MyModule::SomeSubpackage::SomeClass.new("foo")

на самом деле:

const_get(:MyModule).const_get(:SomeSubpackage).const_get(:SomeClass).send(:new, "foo")

что позволяет вместо всех вышеупомянутых компонентов подставить что-то свое не напрягая никого этим фактом.

Более того, данная конкретная идиома применяется в Rails - если у вас в приложении есть файл my_module/some_subpackage/some_class.rb он будет загружен автоматически (require указывать не нужно). Autoload? Не смешите меня. В Ruby можно иметь свой autoload внутри каждого модуля и каждого класса, не трогая всех остальных - потому вместо наворачивания костылей сделан const_missing, из которого надо вернуть обьект соответствующего класса (Module или Class) и method_missing (и отсутствие доступных снаружи свойств объекта), который избавляет например от такого вот.

Более того, method_missing позволяет делать декораторы и прокси-объекты. Например:

class Container
 def initialize(contained)
   @contained = contained
 end
 def method_missing(*args)
   @contained.send(*args)
 end
end
str = "Hello world"
str_in_container = Container.new(str)
str_in_container.include?("world") # => true

Заметьте - не send и call, а именно method_missing (потому что в 90 процентах случаев нужно только это). send и call конечно же также присутствуют (на случай если). Равно как и instance_variable_get если нужно действовать совсем грязно. Или:

7 + 10
x = y

на самом деле:

7.send(:+, 10)
x.replace(y)

И все эти методы можно переопределить самостоятельно для любого класса в системе. Некоторые спросят - а зачем? Ответ им будет прост - в мире где все используемые вами библиотеки не содержат багов - незачем, совершенно. А в суровой кожано-хромированной реальности жизненно необходимо. Особенно когда какая-нибудь библиотека ну никак не могет работать с Юникодом как следует.

И наконец

В предыдущем посте я забыл упомянуть одну крайне важную штуку. Rails - это не система управления контентом и специально делается так, чтобы ничего, связанного с управлением контентом, там не было. И это крайне правильное решение. Вообще - делание универсальных CMS это гнусная болезнь. Rails подразумевает что модель данных всегда создается под задачу вашего клиента, равно как и логика для обработки этой модели. DHH сказал:

Никто не производит контент. Люди пишут обозрения, люди пишут новости, люди пишут статьи, люди публикуют фотографии.

Постарайтесь понять - контента не существует.