Как стать автором
Обновить

Комментарии 197

Сейчас занимаюсь анологичным, только переход идет от ASP MVC 3 -> Rails 3. Код в полтора раза потихоньку сокращается.
Вопрос — что за вызовы title в вашем примере rails контроллера? Это какой то gem?
Это мой хелпер для собирания тайтла в кучу и вывода в шаблоне.
а в чем причина перехода такого?
К сожалению краткого ответа не получится.
Проект — это класический SaaS.
Небольшая триада о платформах для web разработки:
Вообще я считаю, что среди enterprise managed решения для web'а в его 2.0 ипостасии (restful, быстрота разработки, минимум кода, полный TDD и AT) .Net ASP MVC 3 + EFCodeFirst (именно третья версия MVC и CTP CodeFirst) рвет в тряпки java + sping + hibernate, grails и всякие им подобные. Настолько быстро писать проект на managed статическом языке мне еще не удавалось. Единственный аналог из той же java — это play! framework, но он пока достаточно сырой, его разработка как то притормозилось и у меня большие сомнения в его quality по причине отстуствия какого либо покрытия unit test'ами.

Но начав писать проект на еще горячим после релиза ASP MVC 3 я все больше и больше ловил себя на мысли что я пишу чуть ли не на ruby, ибо существенная часть ASP MVC 3 позволят использовать анонимные и dynamic типы (что, ествественно, ускорят разработку) — те же routes ими задаются, ViewBag — это dynamic свойство и т.д. Это очень быстро и клево — но начинаешь терять приемущества разработки используя статический язык — если у тебя чуть ли не треть (а то и половина) кода работает с анонимными типами, ты теряеш статическую проверку и начинаешь ловить баги вследствии опечаток или несоотвествие типов. Refactoring то же оставляет желать лучшего. Конечно на эту проблему есть решение — TDD и AT. Либо не использовать dynamic и анонимные типы и лепить всякие ViewModel — но это реально замедляет разработку (пробывали). Но вот тут статические языки и платформа начинают давать слабену, ибо ничего нет приятнее писать rspec + динамический язык, чем юзать nunit + почти по интерфейсу на сущность + moq. То есть если половина кода не поддается статической проверки на компиляторе, в следствии чего тебе надо писать тесты, то не проще ли взять вообще платформу с динамическим языком и все равно писать тесты, но гораздо быстрее и нагляднее, ибо rails с самой первой версии делалася с оглядкой на тестирование, а в ASP .Net до сих пор многие куски не поддаются тестированию (те же новые async handles). Так же не маловажно отметить поддержку разной конфигурации для dev/prod сред, деплой в одну команду, огромное количество gem'ов и средств для мониторинга производительности и ошибок.

Вторая чисто конкретная проблема проекта была в том, что для него идеального подходил MongoDB. Вроде никаких проблем не предвиделось — есть замечательный NoRM + официальный драйвер. NoRM дал трещину в самой важной для проекта части — он не поддерживал и не поддерживает работу с шардингом. NoRM поддерживается одним человеком и скорого решения этой проблемы явно ждать не стояло. Официальный драйвер вызывает уныние отсутствием поддержки linq и явной заточенности на другие библиотеки.

В том же ruby есть MongoMapper и Mongoid — который поддерживается просто аравой людей, комиты происходят чуть ли не каждый день.

Почему выбрали rails, не django? До этого был проект на django и меня не покидало чувство, что я пишу на ASP MVC 2 — ибо количество кода, хотя python был и тепизирован, было не на столько меньше, чем при использовании ruby + rails, хоть их и ругают за magic (которого стало в разы меньше в rails 3). Да и смущал и сейчас смущает скорость развития django — rails и ругают, что там breaking changes словить при update проще простого, но зато платформа всегда на острие прогресса.

В общем проект еще не закончен, не могу пока заявить, что это будет полный успех rails — покодим увидем.
К счастью в руби все библиотеки и фреймворки для повторяющихся задач используют rake

:D (забавно потому что rake — грабли )
Почему?

Вы еще в php не видели как все делается.
Понятно)
да, перевод конечно
В среде рельс очень любят странные имена, вроде огурца, фабричной девушки, ложкавилки, единорога и так далее.
Ложковилка это что?
Spork, увеличивает многократно скорость тестирования загружая проект один раз.
блин! spoon+fork, как же я раньше не догадался!
Неудивительно. В нашей языковой культуре нет манеры к началу одного слова приклеивать конец второго.
К.О. Докладывает с полей:
Rake == R(uby) (M)ake.
Думаю, многим РНР разработчикам стоит дорости сначала до использования стороннего кода, не говоря уже о фреймворках, а вы тут сразу вылажиаете козыри, пускай помучаются немного =)

Статья безусловно понравилась, большое спасибо!
выкладываете
iBash:
Программисты отлаживают, а филологи откладывают. Кроме того, программисты понимают в чем тут шутка, а филологи только думают, что понимают.
Я программист-филолог (по образованию). Что делать?
войти в рекурсию
Аннигилировать :)
Класть же, класть! Да, не от слова «лажа», а от слова «клад»!!!
Лично у меня проблема с переходом на рельсы или джанго — это развёртывание и поддержка приложения на продакшене. Достался в наследство php код в лучших традициях быдлокодинга — даже шаблоны не выделены, почти каждый из ста+ php файлов содержит <html> и т. д., а те, что не содержат, содержат десяток header(«Loсation: ...») — хорошо хоть формы и их обработка разнесены. Начал переписывать его на рельсах — локально всё ок (тестирование правда не нравится, PHPUnit как-то проще чем RSpec, потому большая часть кода на Ruby была не покрыта, только Селениум), на продакшене проблемы с гемами, сборкой nginx+passenger и т. п., простым «apt-get update & apt-get upgrade» и хуком на коммиты в Mercurial репозиторий не смог найти способа как обойтись и решил, что лучше на symfony2 буду переписывать, тем более, что DataMapper+UnitOfWork покорили моё сердце, хотя когда-то ActiveRecord казалась верхом совершенства при работе с БД.
DataMapper+UnitOfWork в мире рельс об этих вещах мало кто слышал, к сожалению.
А остальное это конечно от неопытности в этом вопросе, Вы использовали capistrano и rvm?
Локально выполнить $ bash < <( curl rvm.beginrescueend.com/releases/rvm-install-head ), как и gem install passenger & passenger-install-nginx-module я смог, а вот на продакшене не рискнул — бог с ними с гемами, всё-таки gem update можно дописать туда же, где есть apt-get update & apt-get upgrade, а вот компиляцию веб-сервера по хрону запускать как-то не нормально, по-моему, и уж точно не debian-way. А capistrano, как я понял, это просто продвинутый rsync, потому не стал с ним разбираться не решив основные задачи.
Капистрано это намного больше чем просто копирование кода. Посмотрите вот эту статью habrahabr.ru/blogs/webdev/110021/

Насчет всего остального посмотрите bundle и в особенности раздел про его Gemfile.lock
Хм, увидел там ваши комменты. Попробуйте разобраться, после этого поймете насколько это отличается от того как обычно привыкли все делать.
Не понял про крон — зачем его использовать?
Тем более вроде в дебиан (в убунте 10.04 LTS точно) есть ruby 1.9.2
А дальше gem и вперед.
Пардон, 1.9.2 в репах, естественно.
Ну сейчас висит на хроне apt-get update & apt-get upgrade раз в сутки. Вкупе с приоритетами разных реп автоматичеcки имею стабильные версии основных пакетов и экспериментальные (в понятиях debian) nginx, php, mysql и т. п. плюс их автоматический запуск при рестарте сервера.

При попытках применить подобную схему для рельс наткнулся на то, что связку nginx+passenger поддерживать актуальной автоматически куда сложнее, чем nginx+php-fpm
У вас проблем с совместимостью еще не было при таком подходе?
Я про то, что на проде я бы побоялся такое делать — в один прекрасный день что-то может и отъехать.
С минорными релизами не было, а мажорные автоматом не ставятся. :)
Админы бы ужаснулись вашим решением )
Потому я не беру на себя хостинг даже разработанных мною до последнего байта приложений :) Только свои личные приложения хостю на своём VDS, остальное максимум заливаю на сторонний хостинг, который сам порекомендовал. Когда начну брать деньги за работу своих приложений, а не за их разработку, то буду нанимать админа, чтобы мне оставалось только заливать свои приложения.
Кстати последнее время я все чаще слышу вот про это github.com/defunkt/unicorn
Судя по посту пакеты для установки всё равно берутся из репозитория ОС, а их там просто нет.
у меня так же ;)
правда, когда в последний раз пытался объяснить эту идею на ЛОРе, не нашлось ни одного человека, кто это бы поддержал. В основном отзывы в стиле «красноглазый фанатик» и «камикадзе».
не знаю что у вас за проблемы с продакшеном, нгинкс собирается автоматом (без проблем), или из папки с сырцами. Или же, можно использовать standalone с проксированием. Никогда не было проблем
Просто мне кажется, что собирать веб-сервер ежедневно по хрону не самое безопасное решение. Из пакетов оно как-то надёжнее, но вот актуальных пакетов не нашёл.
nginx-brightbox_0.6.39-0bbox2_amd64.deb

>Версию nginx-0.8.54 я рассматриваю как стабильную с точки зрения надёжности.

sysoev.ru/nginx/
Лично для меня обновление пакетов на сервере в автоматическом режиме не приемлемо в любом виде. И врядли в этом есть острая необходимость у вас, но как говорится хозяин барин.
Острой необходимости нет, но так на душе спокойней, меньше вероятность, по-моему, что из-за непроведенного вовремя обновления мой сервер смогут использовать, например, для рассылки спама. Это меня волнует больше, чем временная недоступность, благо не админю коммерческие проекты, только личные.
А вот standalone с проксированием почему-то не пробовал даже. Сейчас не могу вспомнить почему то ли отбросил этот вариант, то ли вообще не рассматривал :-/
>>Тут есть пара моментов которые считаются плохим подходом к разработке (везде кроме рельс) — наследование контроллеров и ApplicationController (базовый класс для всех контроллеров). В документации предлагается общую логику используемую в контроллерах переносить в этот класс. Естественно так делать необязательно.

А почему, собственно, считаются плохим подходом?
Как минимум лишняя захардкоденная связь между классами/объектами. Недостаточно знаю рельсы, чтобы сказать что и другие принципы, например, SOLID нарушаются, но явная зависимость налицо, что может усложнять, как минимум, читаемость — десяток методов своих, ещё пара десятков унаследованных и даже один взгляд в IDE на список методов класса уже может в ступор ввести и заставить подумать, что с единственной ответственностью не всё хорошо :)
Я даже больше скажу, в рельсах вот таких вот вещей тьма тьмущая, но сюда я не стал об этом писать. Чего стоят только одни божественные объекты AR.
Когда-то я их называл божественными без сарказма :)
нужно было написать :)
О боже! Пластиковые окна!
о, сеошник детектед :)
Почините детектор. Просто от этих «качественных пластиковых окон» уже тошнит.
Programming languages are like girlfriends: the new one is better because you are better :)
Правда есть один минус по сравнению с php. Невозможно увидеть покрытие тестами вьюх, что при тестировании контроллеров очень важно.

Подробнее можно?
Конечно. Часто в контроллерах получают коллекции которые циклом выводятся в шаблоне. Так же часто ошибка кроется именно там внутри. Не видя покрытие вьюхи можно подумать что контроллер полностью протестирован и все хорошо, но в реальности основной код, который может сломаться, в этих циклах. Это приходится всегда держать в голове и не забывать создавать нужные коллекции.
Можно тестировать вьюхи селекторами. Что-то вроде response.should have_selector(«row», :content => «item #1»)
Да и опять приходим к тому что об этом нужно помнить всегда.
Зачем помнить то, что тестируешь? Он как раз для обратного и сделан — написал тест, забыл, когда сломается — вспоминаешь.
Когда кода много, то невозможно уследить за всем. Для этого и существуют инструменты анализирующие покрытие. И когда в очередной раз Вы захотите поднять уровень покрытия кода тестами, то легко сможете это сделать для всего кроме вьюх. А вот шаблоны придется лопатить вручную сверяя что вы покрыли, а что нет.
мне кажется, SmartBye имел в виду подход классического TDD для создания контроллеров. Контроллер просто не может появиться до того, как появился тест, поэтому можно гарантировать что на каждую фичу есть как минимум один тест. Вы следите не за кодом контроллеров, а за тестами, а за тестами можно следить в стиле «написал, забыл, когда сломается — вспомнишь».
К сожалению это все теория, на практике, особенно в больших командах это не так. Иначе бы не придумывали мерить покрытие.
Есть такая добрая связка вещей, как Cucumber+Capybara+Selenium_webdriver. С помощью нее прекрасно тестятся вьюхи, контроллеры и вообще все, что угодно (в т.ч. отправка почты).
Вьюхи тестятся прекрасно с любым инструментом, я же говорил о покрытии и rcov это не может.
Производительность сильно выросла?
Да, скорость загрузки страниц значительно увеличилось. Специальных замеров не проводил, но все видно и на глаз.
Лучше бы замерил
Не очень честно получится: вместе с переписыванием был и полный рефакторинг.
Вот если отрефакторить старый код, тогда можно будет корректно сравнивать.
И переписать без рефакторинга :)
Вы ещё забыли про замечательный #haml ;)
и #sass для стайлщитов.
ну и coffeescript тогда уже :)
Кстати, не пробовал. Хотя примеры на офф сайте впечатляют.
не, это уже лишняя вещь имхо
Тоже хотел автору в ту сторону указать.
Автор! С этой вещью твой мир может перевернуться, и о шаблонах на ERB или, прости, господи, PHP ты будешь вспоминать с ужасом.
Кто работал с haml — расскажите в чем удобство? Просто более кратко записывается HTML и подстановка данных из контекста? Или какие-то экстра-фичи есть?
Компактный код, очень компактный код. +Удобная вставка вычисляемого кода, в отличие от ERB. Ну и просто удобно. Стоит попробовать раз, чтобы потом уже никогда не возвращаться к erb.
Ну просто нечего добавить.
Я теперь когда erb вижу, а если его ещё и править приходится — просто в лютую печаль впадаю =)
НЛО прилетело и опубликовало эту надпись здесь
Убедили)
НЛО прилетело и опубликовало эту надпись здесь
Fuck yeah! Самозакрытие тегов уже настолько привычно, что я про него забыл :)
Хамла не видел, но ваш коммент пробудил во мне воспоминания о лютом ужасе на питоне (там тоже отступы).

Отступы чреваты, когда ты делаешь что-то не один. А окружающие люди имеют свойство писать код копипастой. Копипаста при копипастинге имеет свойство корёжиться, особенно отступы, что приводит к потере логики. А т.к. человек код писал не сам, а копипастил, то он не понимает смысла скопипасченого, и починить соответственно не может.
НЛО прилетело и опубликовало эту надпись здесь
slim-lang.com — быстрее хамла и синтаксис «более приятный»:
image

И да, гем содержит конвертор haml2slim(правда при виде "%tr<", конвертор оставляет «tr<», что вызывает ошибку).

и #sass для стайлщитов.

И к нему еще Compass.
НЛО прилетело и опубликовало эту надпись здесь
В slim'e, как и в haml можно "#content.example1".
> Принципиальное отличие от ZF, Django, в том что форма создается в шаблоне

Справедливости ради, хочется отметить, что никто не запрещает вам создать форму, используя шаблон:

$form->setDecorators( array( array( 'ViewScript', array( 'script' => 'formTemplate.phtml' ) ) ) );

И в шаблоне писать:

<?= $this->form->email ?>
и т.д.
Ага, только Вы забыли про существования класса этой формы, а в рельсах его нет).
И Вы правда считаете, что это красивее, удобнее и нагляднее, чем в рельсах?
Я, лишь, ответил, что именно это отличие — непринципиальное. В ZF можно создавать формы используя шаблоны. Не обязательно мучаться, пытаясь кастомизировать форму, используя вереницу декораторов.
Бросайте paperclip — переходите на carrierwave.
Ну и конечно haml, delayed_job и еще несколько отличных джемов
ах да, exceptional — отличная штука за 4 бакса в месяц за приложение.
newrelic сильно дорогой в этом плане.
Геолокация с помощью geocoder
Рзаве можно сравнивать exceptional с newrelic? Первое это чисто репортинг эксепшенов, второе, это замер производительности и плюс в довесок репортинг эксепшенов.
Спасибо за carrierwave. Буду разбираться.
Уже года 3 использую paperclip и впринципе доволен.

Чем carrierwave лучше?
он основан на chain of responsibility, поэтому в приложениях с множеством различных типов загрузок файлов код становится более чистым. К примеру, когда у вас одни модели требуют загрузки изображений с одним разрешением, другие с другим, третьи вообще аплоад pdf требуют, становится проще создавать аплоадеры под каждый вид загружаемого, а не под каждую модель
Спасибо за разъяснение, это несомненно плюс по сравнение со «скрепкой».
Пожалуйста, расскажите где там конкретно паттерн Chain of Responsobility?
о, хорошо, что заметили. извиняюсь, у меня ночь была.
основан он на single object — single responsibility, конечно. хотя может и chain там есть, кто его знает.
паперклип почти не обновляется, а carrierwave — вчера вышел 0.5.3. Плюс сейчас многими джемами заведует очень крутой товарищ Jose Valim
спасибо за carrierwave!
насчёт Кариервейв всё неоднозначно.Carrierwave неидеален. Код у него супер. Но вот некоторые юз кейсы с ним очень сложно реализуемы: например, вы не сможете сделать у картинки две версии с разными расширениями, вы не сможете без самописных костылей использовать его со вложенными формами (он не дружит с accepts_nested_attributes), при удалении модели он файлы удалит но оставит пустые папки, которые вам надо самим тереть и так далее.
1. Можно сделать, просто описываете свой метод создания двух картинок, потом process => ваш_метод. Да, придётся извращаться с rmachick, но хранить картинки в 2х расширениях — это тоже не для нормальных людей.
2. Не знаю как у вас, у меня файлы к сообщениям через нестед формы цеплялись только так и не было никаких проблем.
3. Такая проблема есть, но меня она мало волнует. Решается элементарно
1. Нет, как вы говорите ничего не выйдет. Преобразовать и сохранить картинки это просто, но вы не сможете потом получить от карриервейв правильный урл или имя файла, они будет с расширением базовой версии (поскольку в бд хранится только оно). Никакое переопределение методов для версии вам не поможет преобразовать расширение (это возможно но сламается другой функционал карриервейв). Я разговаривал по этому поводу с разработчиками, мне сказали что они очень хотят эту фичу, но архитектура не позволяет.
2. Это проявляется на апдейтах
github.com/jnicklas/carrierwave/issuesearch?state=closed&q=nested#issue/91
Возможно в хеде уже исправили.
по 1 согласен, проблемы с получением пути.
2. Это было !!7!!! месяцев назад
Хотелось бы добавить еще парочку полезных для ruby разработчика вещей:

1) webistrano — интерфейс к капистрано, полезен в том случае, если нужно отделить процесс развертывания оновлений, передав его в саппорт

2) exception_notification — отправляет уведомления в случае возникновения ошибок в приложении на указанный email с содержанием полного трейса ошибки, параметров запроса, сессии и т.д.
exception_notification — очень примитивная вещь и быстро захламляет ящик. Я в статье описал самый лучший сервис на эту тему, а так же его бесплатный аналог.
Насчет примитивизма — это спорное заявление. Ко всему прочему данный гем бесплатен, в отличие от указанного вами сервиса и бывают ситуации, когда в продакшн среде нет возможности использовать внешние сервиса для анализа той или иной информации.
Процитирую себя же:

Кстати существует бесплатный аналог github.com/jdpace/errbit (Errbit is an open source, self-hosted error catcher. It is Hoptoad API compliant so you can just point the Hoptoad notifier at your Errbit server if you are already using Hoptoad).

Эта штука используется на моей текущей работе (один из кор разработчиков ербита наш сотрудник) для крупных, сложных и высоконагруженных проектов.
Вы указываете отдельные приложения для сбора ошибок, exception_notification несколько из иной оперы и служит для интеграции с текущим проектом, не требуя для этого запуска отдельного сервера по сбору информации.
Да, поэтому совершено разные возможности. В любом случае хорошо что есть и ербит и exception_notification).
И потом — всегда полезно знать о бесплатных аналогах )

Ну а с тем, что hoptoadapp.com хорош, я конечно спорить не буду.
также хочу отметить, что вместо state_machine пользователям rails 3 доступен ActiveRecord::Transitions
и ещё, Ancestry в качестве nested set — не лучшее решение, потому как Materialized Path довольно медленный в операциях получения всего дерева. Хотел написать статью на эту тему с вариантом оптимизации, да кармы не хватает.
Ancestry (немного хаченый) — используется в проекте с таблицой на сотни тысяч узлов с частым перемещением и изменением. По своим характеристикам материализованный путь кладет на лопатки все остальные способы вместе взятые.

ActiveRecord::Transitions — вроде же еще не включили в релиз?
Transitions исключили из дефолтной поставки моделей, он включается через include ActiveRecord::Transitions, уже полгода использую.
А поясните, в чём заключался хак ancestry?
Я как понял, хак применяется при переезде со списков смежности на materialized path. мы просто у себя юзаем один метод, приближающий materialized path по производительности получения дерева/поддерева к nested set, при этом практически не снижая производительности добавления/удаления.
И еще перемещение ветки одним запросом.
Еще порекомендовал бы автору пользовать Fabrication вместо factory_girl. Все же, более мощный инструмент.
Для удобной работы с crontab можно использовать гем Whenever github.com/javan/whenever

every 1.day, :at => '4:30 am' do
runner "MyModel.task_to_run_at_four_thirty_in_the_morning"
end


Для новичков, и не только, ориентироваться в гемах поможет сайт ruby-toolbox ruby-toolbox.com
Извините за ламерский вопрос, скажите а хостинги, поддерживающие Ruby у нас есть?
В общем в России его практически не предлагают. Ясно, спасибо!
НЛО прилетело и опубликовало эту надпись здесь
А зачем вообще нужен российский хостинг? Поддержка на русском?
:) давно так не смеялся
Я когда-то на 1gb.ru хостил rails'овый проект. В целом неплохо.
локум ру?
locum.ru
Похоже единственный хостинг, который предлагает ror шаред аккаунты, а не только vps. К тому же можно использовать и mongodb.
юзаю локум, все отлично!
А как быстродействие Вашего проекта после миграции?
Все стало заметно шустрее.
боялся этого услышать :)
И это учитывая что никаких оптимизаций я не делал и все работает на руби 1.8.7. Вот переведу на 1.9.2 тогда вообще полетим).
rvm install kiji — ree 1.8.7 от инженеров Twitter. Быстрее VM для руби, я еще не видел.
я использую ree-2011.03. Тобишь последний.
А как вы сравнивали VM? Давайте тесты, что ли в студию.
мне почему-то переход с php на Ruby не кажется хорошим решением… ну то есть если просто так, без каких-либо обоснованных причин…

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

что касается django — можно какую-то часть выкинуть если не нравится, например, использовать mongodb вместо postgres/mysql или использовать другой шаблонизатор, вообщем, подогнать её под свои задачи и предпочтения

кроме того, кроме джанги есть и другие фреймворки…

я к чему… если кривой фреймворк — это исправить проще, чем кривой язык…

кроме того, деплоймент пайтона и особенно пхп-прилоложений всё же попроще…

Ruby >> Python > PHP

Сейчас занимаюсь проектом на джанге. После рельсы просто тоска. И да, опыт на пхп у меня тоже есть.
Скажите, пожалуйста, в чем конкретно тоска выражается?

Я сам джангист, рельсы не пользовал.
В целом с джангой ситуация странная. Вроде всё есть, но как только начинаешь пользоваться натыкаешься на ограничения.

Ну например, как сделать роут который будет перенаправлять GET запрос на /accounts на один View action а POST на другой?

Хочется написать в views.py:

# GET /accounts
def index(...):
pass

#POST /accounts
def create(...):
pass

итд.

Хочется нормальных миграций написанных руками. Пользоваться syncdb на продакшне просто стрёмно. Да иногда, просто надо выполнить код на питоне в процессе обновления схемы.

Хочется нормальных фикстур типа FactoryGirl, а не хардкора на json.

Хочется отдельных настроек для dev/test/staging/production, а не только settings_local.py.
>Ну например, как сделать роут который будет перенаправлять GET запрос на /accounts на один View action а POST на другой?
Естественно, так как джанга не умеет rest, можно так
def some_thing(request):
    pass

def accounts(request):
    if request.method == 'POST':
        return some_thing(request)


Хочется нормальных миграций написанных руками

South пробовали?
Хочется отдельных настроек для dev/test/staging/production, а не только settings_local.py.
Ну, можно, например, создать папку settings и по файлу настроек на каждый тип.
Как такая вещь в рельсе реализована?
>Естественно, так как джанга не умеет rest, можно так

Пара десятков CRUD контроллеров и в каждом так писать… Плюс учесть что запрос может быть POST, а то и GET, а в нём параметр _method=«DELETE|PUT» (спасибо html, который не хочет поддерживать http полностью :( ), которые нужно так же роутить, как «нативные». В общем когда к REST привыкаешь (я на PHP привык, если что :) ), то как то без него неуютно, а реализовать ручками (может декоратор какой можно написать, я в такие тонкости python не вникал) нудно. Порог вхождения как бы повышается.
А в одном из пыховских фреймворков включение нужного окружения выбирается точкой входа, например example.com/app_dev.php/user/1 — девелоперское, а example.com/app.php/user/1 — продакшен. app.php естественно из путей убирается реврайтом, а app_dev.php на продакшен или не деплоится, или закрывается сервером, да и в нём самом можно REMOTE_IP смотреть и ограничивать, например, только с 127.0.0.1
миграции — South.
Всё остальное ручками. KISS же. Нужно чтобы с первого взгляда была понятна вся внутренняя механика. Умные декораторы — красиво, но нифига не понятно с первого взгляда, совсем не KISS.
Да, Rails не хуже Django. Ну, точнее, в чём-то хуже, в чём-то лучше… Два хороших фреймворка.

А вот если сравнивать ruby и python… Всё-таки как мне кажется Python самый красивый язык программирования, который можно использовать в веб-программировании… А ruby… Был бы я заказчиком — я бы предпочёл иметь решения на php (популярный, а значит, дешевая рабочая сила) или python (хорошо читается, понятный), чем на ruby(перлоподобный). А с позиции разработчика… наверное, оно удобнее, чем на php,… но большинству нравится именно rails, а не ruby…
Расскажите подробнее, в чем же ruby перлоподобный (с perl-ом, к сожалению, слабо знаком). Я вот до начала работы на ROR также искренне верил, что «Python самый красивый язык программирования», но, когда дело дошло до изучения Ruby, выяснилось, что последний не то что не менее красив, чем python, но в некоторых моментах даже приятнее творения Гвидо (никаких призывов к холивару, исключительно субъективное мнение). Тем не менее я по-прежнему люблю Python всем сердцем.

Что касается фреймворков, то с django я успел лишь немного побаловаться год или два назад, с rails пришлось лоб в лоб столкнуться уже на работе. Переход ruby > python был чрезвычайно плавным, с rails было существенно больше проблем — поначалу это все казалось если не читерством, то какой-то невероятной магией (видимо издержки преобладания соглашений над конфигурацией). Однако со временем освоился и, когда возникла необходимость сделать совершенно небольшой (пожалуй даже игрушечный) проект на django, то я пришел в уныние. Быть может я недостаточно знаком с перечнем сторонних плюшек, которые можно навесить на django, но в базовой комплектации при работе с django кода вышло существенно больше, чем я бы ожидал, разрабатывая то же самое приложение на rails. Согласен, что количество кода — это вроде как и не показатель, но с другой стороны именно это количество (при наличие определенного удобства) выливается в прирост скорости разработки. А если к rails добавить несметное множество плагинов и gem-ов, то, на мой взгляд, лидер очевиден. От работы с ROR создается явное ощущение, что вот Это уж точно создано не для кого-то там или для чего-то там, а именно для разработчика, чтобы в первую очередь доволен был именно он =) И это я еще, похоже, и половины мощи ROR на практике не успел оценить. Не знаю, как в сравнении с Zen или Symfony, но django, на мой взгляд, хорош, но слишком отстает — то ли команда разработчиков мала, то ли эти разработчики не достаточно решительны, чтобы привносить во фреймворк радикальные изменения, которые ему ой как нужны.
Вы себе даже не представлете насколько ruby это перл. Посмотрите хотя бы библиотеки которые идут с языком, они один в один перловые.
В смысле из перла в руби взято много разного, конечно разного у них больше чем общего).
Ну это же хорошо! Мне после Perl'а синтаксис Ruby просто отдушина, взяли лучшее от всех :)
В реальной разработке очень важна читаемость и понимаемость кода. В руби она, по сравнению с питоном, хромает. Ибо rails magic.
Быть может я недостаточно знаком с перечнем сторонних плюшек, которые можно навесить на django, но в базовой комплектации при работе с django кода вышло существенно больше, чем я бы ожидал, разрабатывая то же самое приложение на rails
Это утверждение подкреплено какими-нибудь фактами? В рельсах, например, админку надо писать каждый раз — это уже означает, что кода должно быть больше.
>> Это утверждение подкреплено какими-нибудь фактами? В рельсах, например, админку надо писать каждый раз — это уже означает, что кода должно быть больше.

github.com/fesplugas/typus
github.com/sferik/rails_admin

В этом отношении идиология рельс мне гораздо ближе. Все что не основной функционал поставляется в виде отдельных плагинов. И второе это генерация.

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

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

А лично я считаю что админку в принципе нельзя автоматизировать, но можно хотя бы упросить генерацию.
Первое хорошо потому что каждый занимается своим делом, и обновления сторонних библиотек могут идти быстрее самих рельс.
Согласен, это хорошая фича. Однако, что мешает сделать так же (ставить кастомные плагины) для джанги?

И да, все еще хотелось бы увидеть примеры похожих проектов на джанге и рельсах, в которых в рельсоверсии выходило бы гораздо меньше кода.
>> Согласен, это хорошая фича. Однако, что мешает сделать так же (ставить кастомные плагины) для джанги?

Вопрос в том что это делает в ядре джанги? Так же как и комментарии. Но на самом деле ответ известен, достаточно посмотреть из чего появилась джанга.

Не хочу разводить холиваров, но и в джанге и в рельсах и zf я знаю много вещей которые мне совершенно не нравятся и так же в каждом что то нравится.

>> И да, все еще хотелось бы увидеть примеры похожих проектов на джанге и рельсах, в которых в рельсоверсии выходило бы гораздо меньше кода.

Я этого не утверждал).

Да ладно, у меня проблемы с rails magic были лишь в самом начале, поскольку элементарно не хватало знаний. По прошествии некоторого времени и накоплении определенного опыта, ruby ничуть не уступает python-у по читаемости.

По количеству коду я уже сказал, что работать с django довелось совсем немного, поэтому ничего серьезного сказать не могу. А вот базовая админка django — это уж точно не то, чем стоит хвалится. Далеко не всем сайтам она нужна в явном виде, и не столь велик ее функционал, чтобы это нельзя было реализовать самостоятельно. Да и вот — rails_admin. Не берусь утверждать стопроцентно (нет сейчас желания и необходимости вникать), но очень сомневаюсь, что хоть чем-то уступает варианту из поставки django.
Вы меня заинтриговали. Пожалуй, на неделе изучу рельсы.

Как обстоит у них поддержка монги (mongodb)? В продакшене уже можно использовать?
mongoid.org/

Многие плагины его уже поддерживают.
Однако, на своём горьком опыте, хочу отметить, что MongoID 2 до сих пор очень сыр и часто выдаёт очень странные баги. Об этом даже может говорить 20 (!!!) бета-релизов и 8 релиз-кандидатов на данный момент.
Mongoid лично мне не понравился своим закосом под ActiveRecord, что на мой взгляд очень неправильно.
Рекомендую более легкий и простой MongoODM.
Начнем с того, что Ruby все же помощнее, да и покрасивее того же PHP.
Вторая, и самая главная ошибка — вторичность фреймворка. В Hello_World фреймворк вторичен, да. Но в крупных проектах он играет очень важную роль. Речь в статье именно об этом — рельсы проще, гораздо проще поддерживать, нежели ZF. Рельсы — это магия: щелкаешь пальцами — и у тебя уже есть все необходимые сущности, щелкаешь пальцами — и вот уже они работают так, как надо, щелкаешь пальцами — и все это уже крутится на сервере. Рельсы — это основная, а для некоторых и единственная, причина перехода на Ruby. Как при этом фреймворк можно называть вторичным.
> Рельсы — это магия: щелкаешь пальцами — и у тебя уже есть все необходимые сущности

… которые великолепно работают, но ты абсолютно не понимаешь — почему именно. И когда внезапно ты перестанешь быть согласен с тем, как эта магия работает, тебе захочется оверрайднуть стандартный способ, тут-то и начнется настоящая чёрная магия.
Все гемы написаны тем же языком, которым я пишу сайты. Если их работа мня не устроит, я открою их и подправлю. Но все дело в том, что на моем веку такого не случалось ни разу. И в 99,9999999% случаев знать КАК работает гем не нужно — он просто работает.
>> Речь в статье именно об этом — рельсы проще, гораздо проще поддерживать, нежели ZF

Страшное заблуждение. Поддерживать рельсы в больших проектах намного сложнее из-за многих вещей. Особенно доставляет когда пытаешься грепом найти метод, а его, прости господи, не существует. Метапрограммирование, чё.
Насчет метапрограммирования я конечно утрировал, но нужно понимать что php очень простой язык и его действительно легко отлаживать если мы говорим про проекты на рельсах и на zf одного уровня. У меня есть опыт поддержки проектов со многими десятками тысяч строк кода и как я уже писал на zf это было в целом проще, но ruby дает больше возможностей для отладки, например, консоль.
ух ты, прям почти symfony! </trololo>
Это в симфони почти как в рельсах. Рельсы появились раньше.
Сам знаю. И давно уже.
Круто, спасибо за статью, сами используем CakePHP фреймворк на php, основанный по стилистики ROR, тоже встал вопрос о переходе либо на django либо на рельсы, после вашей статьи склонился ко второму)
Буду краток: you make my night…
«You(have) made my night» и «You make my night» имеют разное значение.
Будучи Ruby on Rails разработчиком, я так рад за вас :)
Прямо очень!
Я только начинаю знакомится с рельсами, поэтому у меня есть небольшой вопрос. А при миграции можно сделать так чтобы связи сущностей были и в Database Layer, а не только в Application?
В rails используется ActiveRecord, соответственно связи сущностей описаны в самих моделях (которые один в один мапятся на таблицы). Я правильно понял вопрос?
Вопрос поняли правильно. Дело в том, что при миграции в базу связи между таблицами не добавлялись, что немножко удручало, но как написали ниже есть гемы, которые добавляют эти связи.
Не уверен, что правильно понял ваш англо-русский язык, но вы, вероятно, имеете в виду внешние ключи в БД. Из коробки Rails не предоставляет такой возможности (чтобы не рушить совместимость с SQLite, которая внешние ключи не поддерживает), но в миграциях можно исполнять произвольный sql-код (метод execute). Либо используйте плагин/гем, добавляющий поддержку внешних ключей.
Спасибо, про гемы не знал, не могли бы вы написать названия этих гемов, был бы оч благодарен.
Вроде как вот этот самый крутой — Foreigner

я дико извиняюсь, а вы действительно вот так вот рассылку делаете, т.е. выбрали адресатов и с задержкой в 1 секунду шлете по списку? сколько у вас подписчиков?

и еще вопросик. вот сфинкс все проиндексировал и теперь легко найдет где в базе есть «какая-нибудь строка». как по этой информации теперь определить на каком url встречается та самая строка?
Промахнулся с ответом, он ниже.
>>я дико извиняюсь, а вы действительно вот так вот рассылку делаете, т.е. выбрали адресатов и с задержкой в 1 секунду шлете по списку? сколько у вас подписчиков?

Этот слип там в отладочных целях стоял. А так без задержки.

>> и еще вопросик. вот сфинкс все проиндексировал и теперь легко найдет где в базе есть «какая-нибудь строка». как по этой информации теперь определить на каком url встречается та самая строка?

Мы же ищем не просто по «базе», а по конкретной сущности, например, статье. Конечно в сам индекс может попасть сколько угодно информации из любых таблиц (это все определяется в define_index, но в итоге поиск возвращает уже созданные объекты нашего приложения.

articles = Article.search 'оборудование'
А дальше все как обычно.
Проверка на пустоту -> вывод в цикле (здесь же ссылки).
по 1: а у вас большой список рассылки?

по 2: да, но статьи могут быть привязаны к разным урлам (например «новости о нас» (/ru/about/news), «новости об них» (/ru/linux/must/die/freebsd/4ever/news, «новости об котах» (/ru/sexy/cats). как оно знает? ( я про бекэнд конечно, просто интересно)
1. Не очень, порядка тысячи подписчиков.

2. Вам нужно почитать про полнотекстовый поиск. Каждый индексируемый документ имеет id который мы задаем сами. Поиск находит соответствия в документах и возвращает список айдишников. Дальше мы (или библиотека как в моем случае) делает запрос в базу и достает сущности.

Хотя возможно Вы спрашиваете как каждая статья знает ссылку на себя? Тогда нужно читать про роутинг.
1. ну на тысячи такой фокус еще проходит конечно.

2. да я какбэ очень в курсе и про полнотекстовый поиск, и про роутинг и еще про многое. у вас же есть дерево сайта ( а не тупо /news/show/:news_id, тут-та все понятно), к разным урлам разные контентные единицы привязаны (статика, динамика) в разных комбинациях. одно дело сайт индексатором обойти и по поисковым словам получить список всех урлов, другое дело сделать получить список id только новостей ( и т.д.) и нарисовать этот список в выдаче поиска (туповато, правда?). вот я и спрашиваю, ничего там в рельсах умнее не придумали?
>> у вас же есть дерево сайта
При чем здесь дерево сайта?
К рельсам это отношения вообще не имеет, впрочем, как и ко всем остальным фреймворкам. Поиск всегда ведется по какому то индексу, индекс всегда строится по каким то правилам и привязывается к сущностям приложения, это если говорить о внутренней индексации и я бы не назвал ее тупой, потому что там все может быть очень непросто из-за связанных ресурсов и многих других параметров.
ну да, я немного перегнул насчет сайта, но всё же: представим у нас есть мега-цмс на рельсам (я правда кроме мрачных поделок в виде refinerycms и radiantcms ничего не смотрел), и зададимся тем же вопросом: как бы построить связь между различными «сущностями», коих на странице может быть великое множество, и повторяться они могут из страницы в страницу неисчислимое количество раз, индексом, который нагенерил сфинкс, и конечными урлами страниц.

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

ps. заранее спасибо за минуса
Меня тоже не так давно впечатлили Ruby и Ruby on Rails, планирую на нём что-нибудь попробовать сдедать и внедрить.

Вопрос такой. Во всех книгах по Rails объясняется, как автоматически создавать структуру базы с помощью миграций. А как правильно поступать, если база уже готовая есть, и на Ruby on Rails надо только сделать web-интерфейс к ней? Миграции — это лишь средство облегчить создание базы, или совершенно необходимая вещь для RoR-кода?

И еще прошу подсказать, какие есть подходящие CMS на Ruby on Rails. От сайта потребуется хранение страниц-статей с рубрикацией и новостная лента на главной странице.
Кирилл, а как обстоят дела с модульностью? возможно повторное использование модулей на других проектах?
В этом отношении рельсы намного дальше всех остальных. Посмотри на список гемов которые я привел и что они могут. На каждый чих в рельсах есть свой гем который можно поставить и использовать. И это не обязательно модули в понимании ZF, гемы для рельс могут добавлять любую функциональность, например, бекап приложения на сервера амазона и т.п. Из этих частей можно собирать неслабые сайты не написав почти ни строчки кода. Обязательно зайди посмотри список категорий на этом сайте ruby-toolbox.com/ и количество гемов на каждую, и это только самые известные.
> В этом отношении рельсы намного дальше всех остальных
почему так категорично :). ты использовал бандлы в symfony2?

> На каждый чих в рельсах есть свой гем который можно поставить и использовать
ага, понятно. я думал все немного по другому.

а можно при этом частично переопределять функционал гемов в своем приложении?
>> почему так категорично :). ты использовал бандлы в symfony2?

Текущей инфраструктуре рельс много лет и симфони еще очень далеко до этого уровня. Посмотри как управляются гемы habrahabr.ru/blogs/ruby/85201/

>> а можно при этом частично переопределять функционал гемов в своем приложении?
Обычно они все неплохо кастомизируются сразу при этом в руби постоянно практикуется форк на гитхабе (если посмотреть профиль любого рубиста на гитхабе то можно увидеть десятки форков) и свои правки с последующим пулреквестом и уж если совсем что то нестандартное, то можно изменить текущий класс без наследования (руби же!), но такая необходимость бывает редко.
Привет!

Помню, когда мы с тобой верстали okinfo, еще под ZF, ты считал Рельсы и все их удобняшки баловством )

У меня, ксати, тоже был работающий проект на ZF, но после того, как рапробовал ROR стало просто противно копаться в старом коде – переписал на Рельсах. Так что отлично понимаю твои чувства.
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.