Ruby FAQ

Материал из Викиучебника — открытых книг для открытого мира

TODO[править]

  • DRb
  • Capistrano
  • MySQL issues
  • Разворачивание приложения на сервере. Связки nginx(apache, pound) + mongrel, nginx(apache) + fastcgi. Различия и предпочтительные варианты.
  • Интро для новичков
  • (добавьте что-то своё)

Документация[править]

Какие книги можете порекомендовать для изучения Ruby, Ruby on Rails?[править]

Ещё есть разные Ruby Recipes, Rails Cookbook и проч. На английском языке почти все из них съедобны, но второстепенны по отношению к упомянутым.

Отдельной строкой: Why’s (Poignant) Guide to Ruby. Книга — шедевр, но на любителя.

Для тех, кто интересуется не только синтаксисом: Structure and Interpretation of Computer Programs aka “Wizard book”.

Может мне кто-нибудь кинуть ссылку откуда можно скачать «Мега книжку»?[править]

Не может. Ищите в гугле. В группе ror2ru уважают чужой интеллектуальный труд (как бы банально это ни звучало).

Есть какие-либо бесплатные книги или документация в сети?[править]

На русском:

Где купить русские переводы книг по Ruby и Rails?[править]

Есть нескольно относительно поганых переводов. Как показывает практика, проще выучить английский, чем искать перевод или, того хуже, местное творчество. Как бы прискорбно это ни звучало.

Русские переводы книг:

  1. Программирование на языке Ruby. Идеология языка теория и практика применения — Фултон Х (The Ruby Way 2nd edition)
  2. Гибкая разработка веб-приложений в среде Rails (AWDWR 2nd edition)
  3. Rails. Сборник рецептов (Rails Recipes)
  4. Learn to Program (бесплатная книга) — азы программирования в целом на примере Руби

Видео с конференций, презентации[править]

Вне времени
2007
2006
  • -
  • -

Какие блоги почитать?[править]

Русскоязычные
Англоязычные

Ruby[править]

Правда, что Ruby очень медленный язык?[править]

Есть разные реализации языка Ruby. Самая широкоиспользуемая на сегодняшний день — MRI (Matz Ruby Interpreter) 1.8.6 является пока что и самой быстрой. Также существует реализация Ruby 1.9 (YARV), JRuby (Руби на чистой джаве), Rubinius (реализация по типу Smalltalk-80, с динамической оптимизацией), IronRuby (версия для дот-нета). Первые три реализации имеют задатки для реального ускорения относительно MRI 1.8.6, но фактически заметной оптимизации в них пока нет (1.9 все-такие реально быстрее процентов на 10, но менее стабильная).

Причины тормозов Ruby 1.8.6
  • Интерпретация, а не использование байт-кода. После загрузки файла, он раскладывается в AST (Abstract Syntax Tree), который интерпретируется рубином. Никакой оптимизации, по типу той, которую делают компиляторы Си или Джавы тут нет. Это основная причина тормозов языка.
  • Динамичность. В Си вызов функции — это одна машинная операция перехода по заранее известному адресу. В Ruby вызов метода — это посылка сообщения и поиск ответного метода. Методы в руби многократно дороже, чем даже виртуальные методы в Си++, но на порядок быстрее, чем общее время интерпретации синтаксиса (см. пред. пункт)
Так ли все плохо?

Да, Ruby медленнее чем Python, Perl, PHP, C, Java, Erlang. Но это не всегда критично.

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

С другой стороны, бывают случаи, когда программа работает, скажем, в 100 раз медленнее, чем на Java, но она работает _достаточно быстро_ для имеющихся задач.

Кроме того, для рубина есть (и используются) удобные средства интеграции с Си, которые позволяют с легкостью выносить простые, но громоздкие для MRI задачи в Си и прикреплять с помощью динамических библиотек (.dll, .so, .bundle).

Есть примеры достаточно сложных и нагруженных систем, где работает Ruby.

Как исправляют?

В первую очередь, делают компиляцию в байткод. Это происходит в YARV и Rubinius, JRuby. Байткод хорош тем, что он прост и его можно оптимизировать и даже компилировать прямо в машинный код, который останется лишь выполнить. Сложность заключается в том, чтобы сохранить динамичность языка, поэтому эти системы не появляются за один день и существует немного примеров успешных реализаций (Smalltalk-80, Self-93, Strongtalk, как варианты).

Компенсация минусов MRI 1.8.x (Matz Ruby Interpreter)[править]

Как преодолеваются различного рода проблемы.

  • Скорость интерпретатора. Особенно сказывается в коде, производящим вычислительную работу (смайлик). Если есть задача что-то посчитать, обработать строку, разобрать XML и т.п., то лучше всего написать для этого C-extension (расширение на Си). Как это делается см. в Pickaxe 2nd ed. или в первой редакции. API MRI позволяет писать на Си практически тот же код, что и на руби благодаря использованию родных рубиновых структур (RArray, RString и т.п.) Даже если переписать код впрямую на т.н. Ruby-C (Си с использованием руби-структур), будет достигнуто серьёзно улучшение работы кода. Во-первых, благодаря тому, что не будет работать интерпретатор, во-вторых потому что вы будете использовать более эффективные примитивы (чистый int вместо Fixnum).

Иногда проще переписать имеющийся код на рубине так, чтобы его стало банально меньше. Так появился Merb, как альтернатива Rails. Основное его достоинство — в несколько раз меньшее время прохода запроса от сетевого порта до пользовательского кода («время диспатча»). Если пользовательский код сам по себе очень быстр, то время диспетчеризации играет большую роль в общем быстродействии. Также Мерб умеет многопоточность, что позволяет сэкономить память, не запуская лишние экземпляры веб-серверов для максимальной утилизации CPU. Рельса же не является «thread-safe».

  • Утилизация 100% CPU, когда требуется 400%. В MRI используются «зеленые потоки» (green threads). Их достоинство — легковестность и большая скорость в сравнении с нативными потоками (уровня ОС), недостаток — утилизация только одного ядра, блокирование всех потоков на операциях ввода-вывода, блокирование всех потоков при выполнении native-кода (в экстеншенах). В случае серверного софта, следует проектировать программу так, чтобы её можно было запускать в раздельных процессах. Например, на четырёх ядрах веб-сервер следует запускать как минимум в 4-х экземплярах и использовать балансирующий прокси-сервер для раздачи запросов между ними (например, nginx). Если веб-сервер не многопоточный, то количество экземпляров может быть и больше количества ядер (Рельса, например, не thread-safe, поэтому веб-сервер монгрел ставит все запросы к ней в одну очередь, блокируя мьютекс перед Dispatcher.dispatch!).
  • Блокирующий ввод-вывод. Существует библиотека EventMachine, которая избавляет от проблем с блокирующим вводом-выводом и предоставляет удобный унифицированный интерфейс для написания истинно event-driven приложений. Библиотека включает в себя реализации на чистом руби (не на всех платформах работает гладко), бандл на Си++ и версия для JRuby. Используется в проксирующем http-сервере Swiftiply. В проекте Rubinius стандартная библиотека использует libev (на Си) для эффективной работы с сетевыми событиями. Считается, что на рубиниусе EventMachine не нужна: стандартная библиотека достаточно эффективна.

Компенсация плюсов Ruby (бывает и такое)[править]

Чрезмерное увлечение созданием DSL (domain specific language), неоправданное использование динамики. Речь идет о *_eval, .method_missing, .send. Общее правило: не следует делать реализацию более умной и сложной, чем того требует задача. Хорошая цитата со страницы о Мербе:

«Be wary of clever code! Cleverness for cleverness sake is not our friend; if something is only slightly more handy but infinitely more complex, then please reconsider your implementation.»

Слишком «умный» код не только тяжел для понимания коллегами или самим писателем спустя некоторое время, но и приводит к ненужным затратам процессорного времени и оперативной памяти.

В частности DSL возникает когда становится очевидным некоторый паттерн. Пока вы не повторили некоторый код в точности пару-тройку раз, не имеет смысла его каким либо образом упаковывать в красивую оболочку метапрограммирования. belongs_to — это уже паттерн. Ваш код — ещё нет.

Кодировки[править]

  • Как успешно работать с Unicode? Уникод — слишком общее название. См. два варианта корректного вопроса:
  • Как успешно работать с кодировкой UTF-8? Читайте подробности ниже.
  • Как успешно работать с кодировкой XYZ? Хранить и обрабатывать данные в UTF-8, принимать и выдавать в той кодировке, которая нужна с помощью iconv (библиотека для одноименной программы).
Строки в руби не знают UTF-8?!

Строка в рубине по-определению — набор байт. Все операции типа string[0,3] управляют байтами, а не символами. Многие библиотеки рассчитывают работать с байтами, поэтому переопределение таких методов с тем, чтобы они понимали UTF-8 — неверный путь. В библиотеке activesupport существует модуль Multibyte (благодарности — Юлику Тарханову), который добавляет к строкам метод chars («прокси» для операций над utf-8-символами).

Чеклист
  • $KCODE = 'u'; require 'jcode' включает «юникод-режим» для ряда методов (они начинают работать с символами): chop!, chop, delete!, delete, squeeze!, squeeze, succ!, succ, tr!, tr, tr_s!, и tr_s. Библиотека jcode довольно ограниченная. Рекомендуется использование activesupport и String#chars
  • require 'rubygems'; require 'active_support'

Для рельсы:

  • в my.cnf (если у вас mysql) везде, где требуется, прописать utf8 (если, разумеется, есть доступ к нему).
  • в database.yml указать encoding: utf8
  • в каждой (!) миграции (для MySQL): create_table "some_models", :options => 'ENGINE=InnoDB DEFAULT CHARSET=utf8' (вместо InnoDB — ваш любимый тип таблиц)
  • в environment.rb — config.active_record.schema_format = :sql (потому что в schema.rb не сохраняются объявления кодировок — тесты будут поломаны)
  • mysqldump ... --default-character-set=utf8 ... — чтобы не получить черт-те что, если в my.cnf не прописана utf-8 в умолчаниях для базы и таблиц.

Что такое символы? или :wtf[править]

Лучшее объяснение: http://www.randomhacks.net/articles/2007/01/20/13-ways-of-looking-at-a-ruby-symbol

Русскоязычный комментарий к нему:

  • Символ — это не строка. Это «число с именем».
  • Наиболее корректное понимание символа на низком уровне — «автоматический enum в Си».
Утечка памяти

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

Можно превращать символы в строки (инспектировать символ):

sym = :something
sym.class         # =>  Symbol
sym.to_s          # => "something"
sym.to_s.class    # =>  String
  • Здесь вы создаете объект класса String, который будет уничтожен мусорщиком.

Можно превращать строки в символы (генерировать символ):

str = "something"
str.class         # =>  String
str.intern        # => :something
str.intern.class  # =>  Symbol
  • Здесь вы создаете объект класса Symbol, который не будет уничтожен мусорщиком.

Общее правило: никогда не превращать вводимые пользователем строки в символы.

Возможная атака: в приложение вводят различные строки, которые превращаются в символы. Расход памяти растет. При достижении максимального числа символов (приблизительно 2 млрд), происходит bus error или segmentation fault.

# try it in irb and wait for death or giant swap
loop { rand.to_s.intern }

ERb[править]

ERb (Embedded Ruby) — Встроенный Руби.

ERb — это вот что:

text
<%= "Hello, world!" %>
more text
Erubis — самая быстрая реализация ERb

Где используется ERb?

  • XML/HTML-шаблоны в Rails
  • фикстуры в Rails (test/fixtures/*.yml)
  • где угодно ещё, где вы пожелаете прогнать некий текст через шаблонизатор.

Есть 3 известные реализации ERb:

  • Собственно, ERb. Входит в состав стандартной библиотеки MRI 1.8.*
  • eRuby. Реализация на Си.
  • Erubis. Реализация на Руби, самая быстрая на сегодняшний день (умеет компиляцию и кеширование шаблонов).

IRb[править]

IRb = Interactive Ruby.

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

~ $ irb --prompt default
irb(main):001:0> :test
=> :test
irb(main):002:0> def m(a)
irb(main):003:1>   puts a
irb(main):004:1> end
=> nil
irb(main):005:0> m 1
1
=> nil
irb(main):006:0>

Рубинисты экспериментируют в консоли, если хотят изучить малопонятный код. Не стоит спрашивать товарища «почему не работает?!», пока вы не поигрались с проблемным кодом в irb.

Полезные опции
  • irb -rsomething делает require 'something' (как и ruby -r)
  • irb --prompt simple включает компактное приглашение:
~ $ irb --prompt simple
 >> "hi!"
 => "hi!"
 >> 
  • irb --prompt xmp выключает всякое приглашение (удобно для копирования кода из консоли в текстовый редактор):
 ~ $ irb --prompt xmp
 "hi!"
     ==>"hi!"
 def method(arg)
   puts arg
 end
     ==>nil
 method 123
 123
     ==>nil
IRb в Rails

script/console открывает irb --prompt simple и загруженным environment.rb

Ruby on Rails[править]

Что такое EDGE и с чем его едят?[править]

Едж — это по-английски «край». Последняя ревизия в репозитории. Когда говорят «сижу на едже», это означает, что используется не некоторая зафиксированная стабильная версия, а регулярное обновление библиотеки самыми последними ревизиями.

Репозиторий можно найти тут: http://dev.rubyonrails.org/

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

Зачем

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

Если вы не покрываете свой код тестами на 99,99%, то использовать едж-рельсу вам будет очень страшно.

Как

Если вы держите свой репозиторий в subversion и хотите регулярно обновлять рельсу, вам пригодится Piston.

Если вы используете Git, то можете просто вычекнуть рельсу в vendor/rails или поступить хитрее — выделить её в отдельный репозиторий, обновлять там с помощью git-svn, а внутри своего репозитория подключить git-рельсу через git-submodules. (Спросите Юру yrashk Рашковского и Олега oleganza Андреева, как это делается :-)

Если вы хотите следить за изменениями по RSS, вам сюда: http://dev.rubyonrails.org/timeline/changeset — настраиваете что вам нужно и подписываетесь (внизу страницы). Если лень настраивать самому, в рассылке проскакивала такая ссылка: http://dev.rubyonrails.org/timeline?changeset=on&max=30&daysback=30&format=rss

Плагины[править]

Плагин это механизм для расширения функциональности Rails фреймворка. Каждый плагин лежит в каталоге vendor/plugins и должен имееть init.rb файл, который подключится при запуске вашего Rails приложения.

Как установить плагин?

Можно использовать стандартный инструмент Rails:

ruby script/plugin install http://pluginrepo.com/plugin

Если вы используете svn, то можно добавить ключ -x, тогда плагин поставится как svn-external. Таким образом, когда вы будете делать svn up, плагины будут обновляться из внешнего репозитория.

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

Если требуется установить плагин, скаченный через Piston (запустить правильно install.rb), то можно воспользоваться патчем или просто заменить содержимое файла script/plugin кодом, добавляющим поддержку Piston.

Где найти нужный плагин для моего приложения?

Ресурсы, CRUD, REST[править]

Разворачивание на сервере (deploy)[править]

Apache + FastCGI

(глючный, встречается на шаред-хостингах)

Apache + mod_ruby

(вроде, самый глючный)

Mongrel

(оптимальный вариант, пока одного монгрела хватает)

Балансировщик + Mongrel-ы

Рельса — не может работать в несколько потоков (а MRI не умеет системные потоки, т.е. не более 100% CPU), поэтому для масштабирования запускается N-ое количество монгрелов на каждой машине. Запросы к ним приходят от балансировщика.

Проверенные балансировщики: nginx, apache, lighttpd. Рекомендуется nginx как наиболее стабильный, легкий и удобный в настройке.

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

Средства разработки[править]

Какие средства разработки на Ruby (и с поддержкой Rails) существуют?[править]

Руби имеет такую особенность, что IDE ему обычно не нужна. Некоторые считают, что из-за отсутствия статической типизации, нормальной IDE для него не будет и это не повод для гордости. На самом деле, бывают довольно умные IDE и для Руби, но опять-таки, не всем они нужны.

  • IDE:
    • RubyMine − наверное лучшая IDE. Кроме специфических Rails фич поддерживает кучу гемов широко используемых Rails разработчиками типа RSpec, Capistrano, HAML, SASS, LESS, CoffeeScript. Для коммерческого использования стоит $69 в год. 30 дней триала.
    • NetBeans − хорошая IDE, но для нормальной работы нужен быстрый компьютер. По воле Oracle, плагин для Руби и рельсов больше не обновляется. RIP.
    • IntelliJ IDEA, с плагином для Ruby. См. п.1. База та же. Стоит от $199 в год. Крайне юзабельна при разработке под JRuby, когда часть когда пишется или переписывается на Java или других JVM языках, типа Scala или Closure.
    • Aptana Studio — Бесплатна, Open Source. IDE на базе Eclipse(со всеми его преимуществами и недостатками) поддержка ruby вторична, но в целом работает. Выгодно отличается наличием view с терминалом прямо в IDE. Сахара в виде авторефакторингов для Eclipse based IDE, на удивление мало.
  • Часто используемые текстовые редакторы:
    • TextMate (Mac OS X only) — де-факто стандарт Rails тусовки. Стоит $53. 30 дней триала.
    • Sublime − Улучшенный и кроссплатформенный клон TextMate, стоит $59, но, а-ля Total Commander, покупки не требует.
    • Vim + rais.vim − И этим всё сказано.
    • emacs − см. пункт выше
    • E-TextEditor − (почти TextMate для Windows)

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

Рейтинг средств разработки

Тестирование[править]

Какие средства для тестирования Ruby приложений существуют?[править]

  • В стандартной поставке: require 'test/unit' (Test::Unit)
  • Чудо-библиотека для Behaviour Driven Development: RSpec (и «rspec on rails»)
  • Дебаггер ruby-debug.
  • Многообещающий Cucumber (тоже BDD)

Хостинг[править]

VPS хостинг[править]

VPS/VDS, виртуальные выделенные сервера. Подойдет любой, на котором соберется Ruby. Расчитывайте на то, что один экземпляр сервера Mongrel может занимать до 70 МБайт (обычно 30–40 МБайт, число зависит от используемых библиотек и их «текучести»), а таких серверов на одно приложение потребуется несколько.

СНГ:

Северная Америка:

Латинская Америка:

Африка:

Азия:

Австралия:

Азия:

Западная Европа:

Shared хостинг[править]

  • http://www.textdrive.com — shared rails хостинг, некогда рекомендуемый официально автором Rails.
  • http://www.dreamhost.com — уже успел испортить себе репутацию :)
В России
  • http://www.bhost.ru — shared Ruby on Rails хостинг на Mongrel.
  • http://locum.ru — Rails ориентированный хостинг-провайдер. (Nginx+Passenger, git, capistrano, популярные gem'ы)

Правила списка рассылки ror2ru[править]

Изначально группа ror2ru создавалась для становления русскоязычного сообщества Ruby on Rails.

Текущее видение:

  • адекватная помощь начинающим,
  • обмен опытом по программированию на Ruby, Ruby on Rails (и др.),
  • обмен опытом по развёртыванию приложений на базе Ruby (веб-серверы и т. п.),
  • обмен опытом вообще в разработке (веб-)приложений (архитектура, производительность, оптимизация и т.п.),
  • постинг интересных событий в рунете (конференции по RoR, доклады, выход книг на русском и т.п.),
  • постинг интересных событий в сфере Ruby/Rails,
  • информирование о новых проектах на Ruby/Rails (в рунете) — это важный момент, т. к. для интересующихся новой технологией, как правило, является критичным наличие работающих приложений, и чем красивее, и интереснее они выглядят, тем лучше :),
  • поиск и предложение работы.
  • (ваше предложение?)