Pull to refresh

Рельсы сошли с рельс: Почему я переписываю Archaeopteryx на CoffeeScript

Reading time 14 min
Views 5K
Original author: Giles Bowkett
Вы бывали на вечеринках, где друзья с работы и друзья из колледжа не разговаривают?

Я запостил видео на Tumblr, которое бы никогда не запостил на Facebook:


Это гитарист, отжигающий под «Bangarang» Skrillex'а.

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

И да, статья действительно о Рельсах, несмотря на затянувшееся вступление :)

Я не запостил это видео на Фейсбук, потому что на Фейсбуке у меня есть друзья из универа (которые, судя по Spotify, слушают Skrillex), а также друзья по рейв-сцене ещё с тех пор, когда я жил в Сан-Франциско. Я на самом деле не знаю их мнения на счет Skrillex, но могу предположить, что они были бы не в восторге, ведь некоторые из них — настоящие техно-пуристы да и вообще музыкальные хипстеры, не переносящие попсу, знавшие дабстеп за годы до Skrillex. На самом деле, я слышал некоторые очень ранние пред-дапстепные записи в Лондоне в 2000-м и я наверняка был не единственным из этой группы друзей, слушавшим такое — а значит, как минимум некоторые из нас знали про дабстеп за десять лет до Skrillex.

Мои старые друзья-хипстеры по рейв-сцене наверняка бы плевались на это видео по той же причине, почему моим музыкально-наивным друзьям по универу оно бы понравилось: Skrillex добился просто феноменального успеха за счет стиля, который по сути является сводной таблицей, вытягивающей колонки из таблиц рока и рейва. Запостить что-то подобное на Фейсбуке как бы означает столкнуть лбами две разные группы, несмотря на их диаметрально противоположные вкусы и несмотря на то, что со всеми ними я не виделся годами. Пустая трата времени.

Это напомнило мне старую цитату от Why the Lucky Stiff:

Когда ты ничего не создаёшь, тебя определяют твои вкусы, а не твои способности. Твои вкусы лишь сужают круг общения и отталкивают людей. Так что создавай.

Я вспомнил об этом, потому что видел отличные презентации на LA RubyConf, единственным минусом которых было огромное количество ехидных подколов в сторону практически всех языков, кроме Ruby. По-моему единственным исключением был Smalltalk, который, как обычно, получил стандартную порцию уважения от рубистов, говорящих про Smalltalk. Раньше мне тоже нравился Smalltalk, но я не люблю идолопоклонничество. Однажды я купил старый Mac Mini у одного рубиста из Лос-Анджелеса, который коллекционировал столько старой компьютерной дряни, что был похож на техно-историка. Одним из экспонатов его коллекции было скучное и унылое руководство по IBM Smalltalk — один из самых безвкусных корпоративных документов, который я видел в своей жизни; к тому же, хороший контр-аргумент крикам рубистов из культа под названием «Smalltalk был самой классной штукой на свете».

Пару лет назад Рельсы были настолько же офигенны, насколько Skrillex — сегодня. Но на дворе 2012 и на Hacker News появился такой пост:

Что мне стоит выучить глубже, Node.JS/Express.JS или Ruby on Rails?

По многим вакансиям требуется знание Рельс, но вроде бы Нода планирует откусить приличный кусок пирога веб разработки в ближайшем будущем.


Другими словами, стоит ли мне учить доминирующую технологию, которая упростит поиск работы, или же мне довериться на новом офигеньчике?

Мы все знаем, что является противоположностью нового офигеньчика.


Действительно, в той теме на Hacker News есть такой ответ:
Рельсы — вчерашний день. Это разжиревший мета-фреймворк, для понимания которого требуется огромное количество периферических знаний.

Само собой, вам стоит фильтровать всё, что вы читаете на Hacker News (если вы вообще воспринимаете это всерьёз), но что вообще означает для Рельс стать «вчерашним днём»? Если смотреть на Рельсы, как на фреймворк, то это утверждение — бессмыслица, но стоит взглянуть на Рельсы, как на модный прикол, как всё становится на свои места. Рельсы были на пике моды пару лет назад, но эти дни уже в прошлом.

Люди приуменьшают влияние моды на разработку, но на самом деле не всё так просто. Как говорил Alan Kay (создатель Smalltalk): "Пока есть вещи, развивающиеся быстрее образования, у нас всегда будет поп-культура".

Рельсы — старые и тупые, а Node.js — новый офигеньчик. Но люди ненавидят Node.js из-за чрезмерного «шума». Лично для меня это выглядит забавным, потому что основной шум вокруг Node.js исходит от людей, которые ненавидят Ноду за этот шум.

Меня не удивляют рассказы о том, насколько Нода дерзкая. Когда Рельсы были в таком возрасте, они были не менее дерзкими. На RailsConf 2007 было огромное количество отличных технических докладов, но кроме того там же собралась критическая масса самовлюбленных придурков. Тогда, насколько мог, я старался игнорировать эту самовлюбленность, а теперь советую поступить так же с Нодой. И вот почему.

У напыщенных и дерзких Рельс было три основных пункта, которыми они тролили старичков из мира Java: паттерны проектирования, долгое время запуска JVM и слишком церемониальны подход к написанию кода, который не соответствовал требованиям разработки простых современных веб-приложений. Сегодня же время запуска Рельс настолько долгое, что коммьюнити пришлось написать Spork — специальных gem, который оставляет окружение Рельс живым между выполнением тестов. Иначе использовать TDD с Рельсами было бы сложно. Выполнение тестов в Рельсах может занимать столько времени, что к моменту завершения вы вполне можете забыть, что вообще вы сейчас пишете, а порой — и собственное имя. Когда коммьюнити Рельс было в возрасте сегодняшней Ноды, они подшучивали над паттернами проектирования. Но посмотрите на реализацию ActiveRecord::Base, который переопределяет «inherited» и вы поймете, что это

class User < ActiveRecord::Base; end
на самом деле означает
User = ActiveRecord::Base.new
или, другими словами,
User = Struct.new(:username)

Мы вынуждены использовать странные и запутанные механизмы, чтобы прикрепить модули ClassMethods и InstanceMethods к ActiveRecord::Base, потому что если мы попробуем отнаследоваться от него, мы не получим наследника в чистом виде. На самом деле мы получим новый класс, который создается при помощи ActiveRecord::Base. Как видно, ActiveRecord::Base на самом деле является скрытой фабрикой ActiveRecordClassFactory.

Что же касается слишком церемониального кода, дайте-ка я расскажу вам про свои яйца. У меня на самом деле есть rake-таск для почёсывания яиц. Кто-то однажды сказал мне, что настоящий программист должен непременно написать код для почёсывания своей промежности, а я серьёзно подхожу к таким вопросам. Мой код использует последовательный порт для управления Arduino. У Arduino есть серво-привод, к которому прикреплена чесалка. Весь этот механизм расположен на полочке у меня под столом, на уровне пояса.

Мне в буквальном смысле приходится писать «bundle exec» каждый раз, когда я хочу почесать себе яйца. А я не в восторге от необходимости писать «bundle exec» каждый раз, чтобы почесать свои яйца. Я назвал задачу «balls», чтобы я мог писать «rake balls», ведь она скребёт мне яйца («because it rakes my balls» — прим. пер.), а Bundler обосрал весь мой красивый синтаксис. Вы думаете, я жалуюсь? Вы думаете, я стараюсь обратить ваше внимание на то, что требовать от меня писать «bundle exec» каждый раз, когда я хочу почесать собственные яйца — означает проявлять невероятное призрение ко мне, как к юзеру? В конце концов, я ведь использую rake именно потому, что пишу на языке, который призван облегчить работу программиста! Но конечно же нет, я не стану говорить ничего такого, ведь это будет не конструктивно, да и делу не поможет, так что я просто печатаю «bundle exec rake balls», чтобы почесать себе яйца в гробовой тишине.

Необходимость печатать «bundle exec» каждый раз, когда я хочу почесать себе яйца — это олицетворение чрезмерно церемониального кода, на который плевались Рельсы в период с 2005 по 2007 год. Коммьюнити Рельс превратилось во всё то, что само высмеивало. Несмотря на это, они смогло фундаментально изменить веб-разработку в лучшую сторону. И не только в Руби, но и практически во всех других языках. Когда Рельсы только появились, они запустили волну клонов, которые расцветали в других языках практически ежедневно. По мере взросления Рельс, другие платформы тоже взрослели. Сегодня мы не видим новых клонов Рельс, которые появляются в каждый вторник, как это было в 2006-м. Зато мы видим, как коммьюнити Рельс создает генераторы кода, конвенции прежде конфигураций и аккуратненькие раутеры каждый раз, когда оно покидает свою зону комфорта. Например, CoffeeScript получил свою дозу вдохновения и от Руби, и от Рельс, ставя девелоперское счастье наивысшим приоритетом.

Именно поэтому я думаю, что прислушиваться к шумихе вокруг Ноды — глупо. Это не стоит потраченных нервных клеток. Шумиха приводит к пустым спорам сторонников и противников. Это бессмысленно, просто забейте. По мере развития, Нода будет меняться, впитывая всю критику. Так же, как и Рельсы в своё время. А пока что вокруг идёт много интересной работы. Люди создают замечательные вещи, а браузеры развиваются такими темпами, что к моменту, когда Нода немного подрастет, принципы веб-разработки существенно изменятся.


То же самое происходило и с Рельсами. Именно потому писать под Рельсы было так весело, пока Рельсы были на коне. И именно потому сегодняшние Рельсы — это мощный и полезный инструмент. Но всего лишь инструмент.

Тем не менее, возвращаясь к той цитате от Why the Lucky Stiff, бессмысленно ненавидеть Рельсы за то, что сейчас они не такие модные, как раньше. Конечно, можно смотреть на Рельсы, как на динозавра, вышедшего из моды, но намного конструктивнее смотреть на них, как на полезный инструмент для создания разных штук. Но и тут нас тоже ждёт пара проблем. Давайте забудем про аргумент «Рельсы — вчерашний день», но вернёмся к этому комментарию на Hacker News:

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

Первое, что мне это напоминает — бессмысленный вброс, сравнивающий Рельсы с «ношением трусов на голове». Я не могу согласиться с этой точкой зрения, потому что большинство этой критики применимо только к тому, как официальная документация советует вам использовать Рельсы, а не к тому, как серьёзные, известные, отборные Rails-разработчики используют их (за исключеним, разумеется, самого DHH). Я думаю, что аргумент про «огромное количество периферических знаний» попал в яблочко. И главное среди этих периферических знаний — это понимание разницы между тем, чему вас учит официальная документация Рельс и тем, как на самом деле поступают разработчики.

Например, я не могу себе представить, чтобы кто-то кроме DHH и, возможно, пары других разработчиков Рельс на самом деле использовал рельсовые тесты так, как рекоммендуют сами Рельсы. Я не думаю, что кто-то кроме DHH и, возможно, пары других разработчиков Рельс вообще воспринимает всерьёз официальный подход Рельс к тестированию. Рельсовые модульные тесты на самом деле не модульные, рельсовые интеграционные тесты на самом деле не интеграционные, а рельсовые функциональные тесты — нифига не функциональные. Большинство разработчиков просто создаёт директорию «spec», ставит RSpec и выкидывает к чертям всё остальное. Так что приводить такие аргументы в споре против Рельс — пустая трата времени.

В аргументе «Рельсы — старые и тупые» часть про «старые» можно проигнорировать. «Старый офигеньчик» означает «классика». Но «тупые» — это то, на что стоит обратить внимание, потому что в Рельсах действительно хватает тупой фигни. Укадайте-ка, что случится, если забыть поставить «source :rubygems» первой строчкой в свой Gemfile?

Ваш Gemfile не содержит ни одного источника. Вы можете добавить источник при помощи строки типа 'source :rubygems'

Вы чё, бля, издеваетесь?!

Вот как выглядела бы подсказка Гугла «возможно, вы имели в виду», если бы её разработала команда Бандлера:

Перевод: Возможно, вы имели в виду «бритни спирс». Тогда пожалуйста, введи свой поисковый запрос правильно, грёбанный тупица.

Bundler делает управление зависимостями очень простым по сравнению с тем, как было раньше, но из-за того, что 'source :rubygems' не включен по умолчанию (хотя Бандлер знает, что он должен быть включен), Бандлер терпит полную неудачу в применении конвенции прежде конфигурации. И я не имею в виду «могло бы быть лучше», я имею в виду «тебе кол, незачёт, остаёшься на второй год». Это всё равно, что «малость провтыкать с одеждой», придя на работу в одних трусах, надетых на голову, да ещё и в грязных.

Bundler — не единственная проблема. С появлением Rails 3, Рельсы сошли с рельс.


Перевод: Rails 3 позволяет создавать новые приложения проще:…

Эта ссылка иронична, она ведёт на гигантскую страницу со списком вещей, которые нужно сделать, прежде чем можно начать писать своё приложение.


Перевод: Когда я начинал учить рельсы, примерно версии 0.6, у меня был один исполняемый файл, который устанавивал руби + рельсы. Я печатал одну команду и начинал кодить.

Зацените эту дискуссию:

Перевод:
@topfunky: Rails 3 обещали возможность «собрать свои маленькие рельсы» только с тем, что тебе надо. Кто-нибудь на самом деле этим занимается?
@jashkenas: @topfunky я не думаю. ИМХО, последствия от мерджа Merb'а — это пока что самое печальное, что произошло с Рельсами.
@j3: @jashkenas а можно поподробнее? /cc @topfunky
@jashkenas: @j3 Весь прогресс заглох на два года, третьи Рельсы во многом *до сих пор* тормознее вторых, Bundler — это кошмар, Node.js победил.

Остальное можете почитать здесь, если хотите. Я просто приведу пару отрывков.


Перевод: @tomdale Окей. Для приложений с нуля, я бы наверное выбрал Ноду. Если бы Рельсы действительно развивались последние 3 года, возможно, всё сложилось бы иначе.


Перевод:
@jashkenas: @tomdale Согласен по всем пунктам. В принципе, я просто расстроен, что третьи Рельсы не выглядят качественно лучше вторых. Те же фичи, другой API.
@josevalim: @jashkenas @tomdale если оценивать Rails 3 только с позиции разработчика приложений, то да. но третьи рельсы всегда были направлены на коммьюнити разработчиков плагинов.

Если перефразировать Хосе, Rails 1 и Rails 2 предназначались разработчикам приложений. Rails 3 предназначены для создателей плагинов и программистов, которые поддерживают существующие приложения. Это всё здорово, но создавать фреймворк приложений, игнорируя разработчиков приложений как основную целевую аудиторию — это как раз одна из вещей, которую Рельсы высмеивали в Джаве в 2006-м. Хосе — один из основных разработчиков Рельс и он написал потрясающую книгу, описывающую невероятную силу нового модульного API третьих Рельс, но порой твиты звучат громче книг.


Перевод: «Node.js – это будущее серверных приложений» @wardcunningham #nodepdx

Уорд Каннингем – это нехилый такой аргументик.

Мой ответ тому парню с Hacker News, который спрашивал, стоит ли ему учить Ноду или Рельсы — такой же, какой бы он получил от Jeremy Ashkenas (автор CoffeeScript — прим. пер.): учи Ноду. (На самом деле, я не могу говорить за Джереми, так что скорее учи и то, и другое, но больше внимания удели Ноде). Порой весело быть тусовщиком, а музыка за соседней дверью сейчас веселее. На сегодняшний день важнее учить Node.js, CoffeeScript и Backbone, потому что работа, которая кипит в этих сообществах, меняет парадигмы. Текущая же работа с Рельсами заключается в причёсывании парадигм, которые Рельсы меняли в своё время — правда, третьи Рельсы добавили столько же острых углов, сколько и убрали.

Кстати, про острые углы. Браузер превращается в операционную систему. Если у вас новая версия Хрома, вы уже можете поиграть с браузерной драм-машиной, а так же с фильтрами, компрессорами и синтезаторами. Конечно, на данный момент это может закончиться вылетом браузера, но скоро всё будет офигенно. Также, весьма вероятно, что веб-приложения станут выглядеть устаревшими по сравнению с мобильными приложениями, а Ноде будет проще получить от этого выгоду, чем Рельсам.

Когда вы учите что-то новое, вам хочется, чтобы это было весело. Рельсы до сих пор полезны, но больше не заводят. Хотя у них полно офигенных штук, воздух так же наполнен всякими «какого хрена? чем они вообще думали?!». Разгребать это говнище — удовольствие не из приятных. Если вы хотите работать с тем, что будет приносить удовольствие, попробуйте Clojure, Scala или Node.js. Clojure и Scala работают на основе Java, воспоминания о которой до сих пор не дают мне спокойно спать ночами, а Node.js подразумевает язык, писать на котором мне весело, несмотря на его частые глупости. CoffeeScript далеко не идеален, но писать на нём приятно, потому что он снижает WAT-фактор JavaScript'а до приемлемого уровня фонового шума.

Rails – это уже не будущее, а прошлое.

http://www.youtube.com/watch?v=WM1RChZk1EU

Я думаю, что сейчас проще найти хорошую работу с Node.js, чем хорошую работу с Rails. Но лично мне интереснее работать над собственными проектами, на которых я точно так же получаю удовольствие от Ноды. Так что я готовлю серию видео, в которых создание музыки будет использоваться для обучения Node, CoffeeScript, Backbone, Socket.io и, что самое главное, jasmine-node – порту джаваскриптовой BDD-библиотеки Jasmine на Node.js. Используя jasmine-node, вы можете выполнять ваши спеки на сервере в большинстве случаев (или вообще всегда — подробности расскажу в этих видео), причём выигрыш — просто офигенный.

Мне никогда не нравилось выполнять спеки в браузере. Моментально выполнять их в коммандной строке — огромное наслаждение, ведь можно подпихнуть их в continuous integration, да в принципе куда угодно, используя юниксовые коды возврата. Серьёзно, в 2012-м году уже не осталось отмазок, чтобы не писать свой джаваскрипт в стиле TDD/BDD.

Возвращаясь к теме джаваскриптовой драм-машины, я написал библиотеку на Руби, которая называется Archaeopteryx. Это комбинация MIDI-интерфейса, драм-машины и вероятностного импровизатора брейкбита. Я начал переписывать его на CoffeeScript. Новая версия называется Clyde и её код стал намного чище.



А ещё я приготовил парочку действительно весёлых хаков.



Я выбрал название Клайд отчасти потому, что мне задавали слишком много вопросов о том, как правильно произносить Archaeopteryx (Археоптерикс), но в основном — в честь легендарного барабанщика Клайда Стаблфилда — не просто крутого барабанщика, а самого крутого барабанщика, про которого пел Джеймс Браун — который, кстати, будет ДОКЛАДЧИКОМ на Madison RubyConf в этом году. Это та же конференция, на которой я распсиховался в прошлом году после фразы о том, что тестировать JavaScript — не обязательно. Я даже не могу передать, насколько я взволнован.

Справедливости ради, Ari Russo написал потрясающую MIDI-библиотеку на Ruby под названием Unimidi, которая выглядит намного лучше всего, что я сам когда-либо писал, но для этого проекта я остановлюсь на JavaScript. Частично — потому, что мне кажется более выгодным инвестировать своё время в этот язык, а не в Руби (особенно потому, что я буду повторять те же вещи, которые уже делал в Руби), а частично — потому что я верю в его технологическое превосходство.

Кстати, дело не только в том, что Клайд проще произносить. Многие люди жаловались, что Археоптерикс тяжело читать. Несмотря на то, что Клайд находится в активной разработке, его исходники уже намного проще читаются. Во-первых, мне пришлось натырить много низкоуровневых MIDI-интерфейсов для Археоптерикса из отличной книги за авторством Topher Cyll под названием Practical Ruby Projects (Практические Проекты на Ruby). (Позже Ben Bleything переписал их, создав более чистую интерфейсную библиотеку под названием MIDIator). С другой стороны, чтобы добавить поддержку MIDI в Клайд, мне достаточно было установить отличную Node.js-библиотеку и написать немного простейшего кода. Целые куски кода Археоптерикса посвящены имплементации джаваскриптовых эквивалентов setTimeout() и копированию lambda в L, чтобы объектам можно было свободно назначать методы. Типа того, как мы передаем функции в JavaScript.

Грубо говоря, JavaScript лучше подходит для проектов такого типа, потому что Археоптерикс использует кучу хаков только для того, чтобы Ruby начал работать, как JavaScript. И хотя JavaScript сам по себе довольно вырвиглазный, CoffeScript настолько красив, что порой заставляет Ruby выглядеть неуклюжим.


Перевод:
@gilesboatboy: каждый раз, когда я вижу do |foo|, во мне просыпается маленький задрот, желающий убивать. как это назвать? задротогнев? ведь «do» — совершенно лишние буковки :-p
@judsonlester: если бы в Руби были настоящие макросы, тогда в этих буковках небыло бы необходимости.
@topfunky: где мой CoffeeScript для Ruby?! пускай компилятор использует отступы, которые все и так пишут, вместо бесполезных do-end.

Ребятам, которые игрались с Клайдом, также понравилась простая интеграция с Garageband, а значит любой пользователь Мака сможет легко и просто поднять у себя Клайд, в то время, как попытки установить Археоптерикс на свой комп ставили в тупик многих. Опенсорсный проект, который работает только на машине автора — бесполезен.

Мне нравится идея моих видео, потому что они будут обучать передовым технологиям при помощи весёлых и интересных примеров. Они на самом деле могут стать лучшим, самым увлекательным способом научиться современной разработке на JavaScript. По-моему важно, чтобы обучение разработке софта было весёлым, потому что я хочу вдохновлять людей на поиски собственных хакерских решений, ведь лучше всего мы запоминаем то, на чём концентрируемся. Этой идеей пронизаны наши хакерские языки: когда мы изучаем новую технологию, мы говорим, что «играемся с ней». Завтра после обеда я бесплатно опубликую моё первое видео, так что можете заглянуть сюда в пятницу (вот оно — прим. пер.).

Так как этот блогпост — в какой-то степени реклама этих видео, а в рекламе прежде всего важна правда, я должен признаться, что на самом деле у меня нет rake-таска для почёсывания яиц. И всё же, у меня сложилось впечатление, что мне нужно печатать «bundle exec» при каждом почёсывании яиц, хотя этой херни можно было бы избежать при помощи минимальных знаний о путях и переменных окружения Unix. (Ещё немного нытья про Бандлер: если написать «bundle && foo», вы никогда не попадете в foo; похоже, что Бандлер вообще не поддерживает коды возврата).

Возвращаясь к глобальной проблеме, Рельсы однозначно сошли с рельс. Чистый и модульный API — это важная цель, но не такая важная, как скорость разработки, современный набор фич (почему Рельсы до сих пор не поддерживают HTML5 так, как в своё время поддерживали Ajax?) и, прежде всего, счастье программиста. Интеграция Merb'а была огромным и трудозатратным отходом от цели, принесшая лишь небольшую выгоду, а DHH, написавший целых две книги о том, почему стоит отказываться от добавления новых фич, должен был срубить эти начинания на корню. Я, всё же, продолжу использовать Рельсы, потому что они до сих пор остаются замечательным фреймворком, но по-моему будет абсолютно справедливо утверждать, что Rails 3 стали шагом назад относительно Rails 2, а Бандлер, каким бы полезным он ни был, всё ещё очень далёк от идеала. Они говорят, что дошли до версии 1.0, но я не думаю, что кто-то воспринимает это всерьёз.

Апдейт: Yehuda Katz, один из разработчиков Бандлера и Рельс, прислал мне вот этот полезный кусок кода:

~/Code/ember.js ‹ruby-1.9.3›  ‹master*› $ bundle && echo "fuck you giles"
Using rake (0.9.2.2) 
Using confparser (0.0.2.1) 
Using multi_json (1.0.4) 
Using execjs (1.2.13) 
Using libxml-ruby (2.2.2) 
Using faster_xml_simple (0.5.0) 
Using httpclient (2.2.4) 
Using json (1.6.5) 
Using nokogiri (1.5.0) 
Using net-github-upload (0.0.8) 
Using github-upload (0.0.2) 
Using rack (1.4.1) 
Using thor (0.14.6) 
Using rake-pipeline (0.6.0) from https://github.com/livingsocial/rake-pipeline.git (at master) 
Using rake-pipeline-web-filters (0.6.0) from https://github.com/wycats/rake-pipeline-web-filters.git (at master) 
Using sproutcore (0.0.1) from https://github.com/wycats/abbot-from-scratch.git (at master) 
Using uglifier (1.0.4) 
Using bundler (1.1.rc.7) 
Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.
fuck you giles
Tags:
Hubs:
+46
Comments 94
Comments Comments 94

Articles