Используем bundler правильно

28 февраля 2012, 16:16
Данная заметка скорее является выдержкой из перевода man'а к гему bundler, однако хочется заострить внимание (в том числе и наше) на описанном ниже моменте:

bundle install vs bundle update

Поведение bundler немного отличается в зависимости от того, где он запускается: на компьютере разработчика или сервере, где будет запущен проект.

Первый запуск bundler на компьютере разработчика

В данном случае, согласно документации, необходимо выполнять команду:
# bundle install

После этого bundler просмотрит все зависимости для gem'ов из Gemfile и установит всё необходимое для работы приложения. После этого, вся информация о зависимостях и установленных gem'ах будет сохранена в файле Gemfile.lock. Данный файл необходимо добавить в систему контроля версий! Он будет использован в дальнейшем.

Обновление gem'ов до последних версий

Если разработка приложения заняла продолжительное время и вышли обновлённые версии для некоторых gem'ов, в какой-то момент их придётся обновить. Для этого существует команда:
# bundle update

После её вызова bundler проигнорирует содержимое файла Gemfile.lock, заново подберёт все необходимые к установке библиотеки и обновит необходимые из них. Также, в случае если нужно обновить какой-то один gem из Gemfile, можно в конце команды указать его название. Например, так:
# bundle update rails

Это обновит лишь gem rails, оставив остальные на текущих версиях.

Установка зависимостей на компьютере нового разработчика

Если в команду добавился новый разработчик, или разработка "переехала" на другой компьютер, установить необходимые версии gem'ов поможет команда
# bundle install

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

Установка gem'ов на сервере

Здесь всё просто.
# bundle install --deployment

Данный случай очень похож на вариант с новым разработчиком. Единственное отличие в том, что в случае с сервером, все gem'ы устанавливается в каталог vendor/bundle. Это объясняется тем, что в разделяемом окружении изоляция важна. И к тому же, у пользователя может не хватить прав на установку gem'ов в системые пути. Либо у веб-сервера - прав для их чтения.

Изменение Gemfile

Если в Gemfile были внесены изменения (например, добавлены новые gem'ы), то Gemfile.lock больше не будет содержать правильной информации. В этом случае, например, установка зависимостей на сервере завершится неудачей. Для перегенерации данного файла в очередной раз необходимо вызвать команду
# bundle install

Bundler распознает несоответствия в Gemfile и Gemfile.lock и проигнорирует последний файл, в итоге заменив его на правильный.

Вот и всё. Довольно просто. Приятных выходных!

Ошибка в посте

12 декабря 2011, 13:09
Оказывается, в нашем недавнем посте про запуск Ruby on Rails в связке с Nginx+Unicorn закралась ошибка! Увидели, исправили, обновили, извиняемся.

Ruby 1.9, Rails и invalid byte sequence in US-ASCII

24 ноября 2011, 00:54
Готов поспорить, если у вас есть legacy-проект на Rails 2.3, в котором до сих пор используется версия ruby 1.8.7, то не раз была попытка перехода на 1.9, в погоне за новыми возможностями и ускорением работы приложения :)
И раз проект все еще на 1.8.7..
Обычно, проблемы возникают с кодировками: русскими текстами, записанными в .erb, или строками на русском языке, возвращаемыми из MySQL.

Возникающие ошибки проявляются в виде сообщений типа:
invalid byte sequence in US-ASCII
или:
incompatible character encodings: UTF-8 and ASCII-8BIT.

В Интернете довольно много разношерстных решений данной проблемы. Попытаюсь собрать их в одном месте.

environment.rb

В самое начало необходимо вставить такие строчки кода:
Encoding.default_internal = Encoding::UTF_8
Encoding.default_external = Encoding::UTF_8
Подробнее можно почитать по этой ссылке: http://blog.grayproductions.net/articles/ruby_19s_three_default_encodings. Там объясняется смысл этих строк.

config/initializers/patches.rb

# Patching MySQL:
#
require 'mysql'

class Mysql::Result
def encode(value, encoding = "utf-8")
String === value ? value.force_encoding(encoding) : value
end

def each_utf8(&block)
each_orig do |row|
yield row.map {|col| encode(col) }
end
end
alias each_orig each
alias each each_utf8

def each_hash_utf8(&block)
each_hash_orig do |row|
row.each {|k, v| row[k] = encode(v) }
yield(row)
end
end
alias each_hash_orig each_hash
alias each_hash each_hash_utf8
end

# Patching ActionController:
#
module ActionController
class Request
private
def normalize_parameters_with_force_encoding(value)
(_value = normalize_parameters_without_force_encoding(value)).respond_to?(:force_encoding) ?
_value.force_encoding(Encoding::UTF_8) : _value
end
alias_method_chain :normalize_parameters, :force_encoding
end
end
Данный код делает примерно то же самое, но специально для MySQL и ActionController.
Эти способы нашим проектам - помогли. Надеюсь и вашим тоже :) Удачи!

Запуск Ruby on Rails на VPS с Debian Linux

08 ноября 2011, 22:51
Итак, прочитав наши недавние посты и успешно установив Rails на ваш VPS или ruby-хостинг, пора ознакомиться с самым главным - непосредственно запуском RoR на хостинге. Следуя традициям, я расскажу как это делается на VPS с Debian Linux на борту, однако с остальными дистрибутивами последовательность действий будет примерно та же.

Nginx

Естественно, в качестве фронтенда мы будем использовать сервер nginx. Думаю, почему мы сделали такой выбор, объяснять не нужно.

Для начала устанавливаем сам сервер:
# sudo apt-get install nginx
Напомню, что если вы вошли в систему под пользователем root, то необходимости в команде sudo - нет.

Теперь добавляем конфигурационный файл для нашего веб-приложения (сайта). Для этого в каталоге /etc/nginx/sites-available создаем файл с именем домена, на котором будет размещаться веб-сайт. Допустим это my.o1host.net :-)

Тогда содержимое файла /etc/nginx/sites-available/my.o1host.net должно выглядеть примерно так:
server {
 listen 80;
 server_name my.o1host.net;
 access_log /var/log/nginx/my.o1host.net-access.log # путь к файлу с логами

 location / {
  proxy_pass http://unix:/путь/к/приложению/tmp/sockets/unicorn.sock/;

  # чтобы rails могли определить IP клиента:
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

  proxy_connect_timeout 90;
  proxy_read_timeout 600;
  proxy_send_timeout 600;
 }
}

Что происходит в этом конфигурационном файле? Мы указали, что при приходе запросов к сайту http://my.o1host.net/, nginx должен перенаправить их на локальный Unicorn, который ожидает соединений используя unix-сокет, расположенный в папке нашего приложения. И заодно мы указали несколько таймаутов, по истечению которых (если от веб-приложения не будет ответа) - мы увидим всем знакомое сообщение.
Хочу предупредить, что указанный конфиг - минимально работоспособный и не самый оптимальный. Со временем, вам понадобится более тонкая настройка некоторых параметров. Но когда до этого дойдет дело, думаю вы уже без проблем справитесь :)

Теперь, согласно концепции Debian, нам необходимо включить только что настроенный сайт. Для этого необходимо в каталоге /etc/nginx/sites-enabled разместить символическую ссылку на конфигурационный файл.
Сделать это можно с помощью команды:
# cd /etc/nginx/sites-enabled
# sudo ln -s ../sites-available/my.o1host.net my.o1host.net

И затем попросить nginx перечитать конфигурацию:
# sudo /etc/init.d/nginx reload

Если все сделано правильно, nginx скажет что с конфигурационным файлом все окей и зайдя по ссылке на ваш веб-проект, вы увидите радостное сообщение о том, что пора приступать к запуску unicorn!

Unicorn

Вообще, выбор серверов для запуска Rails - многое множество. Сначала это был старина Mongrel, затем многие переключились на Passenger. В последнее время набрал популярность Unicorn. Отметим также, что еще хорошо известен сервер Thin, но в отличие от перечисленных ранее, мы не имели возможности с ним поработать.

Итак. Первым делом установим gem под названием unicorn и, зайдя в каталог config нашего приложения, создадим там файл unicorn.rb с таким содержанием:
worker_processes 2
working_directory "/путь/к/приложению/"

# This loads the application in the master process before forking
# worker processes
# Read more about it here:
# http://unicorn.bogomips.org/Unicorn/Configurator.html
preload_app true

timeout 30

# This is where we specify the socket.
# We will point the upstream Nginx module to this socket later on
listen "/путь/к/приложению/tmp/sockets/unicorn.sock", :backlog => 64

pid "/путь/к/приложению/tmp/pids/unicorn.pid"

# Set the path of the log files inside the log folder of the app
stderr_path "/путь/к/приложению/log/unicorn.stderr.log"
stdout_path "/путь/к/приложению/log/unicorn.stdout.log"

before_fork do |server, worker|
# This option works in together with preload_app true setting
# What is does is prevent the master process from holding
# the database connection
defined?(ActiveRecord::Base) and
ActiveRecord::Base.connection.disconnect!
end

after_fork do |server, worker|
# Here we are establishing the connection after forking worker
# processes
defined?(ActiveRecord::Base) and
ActiveRecord::Base.establish_connection
end

Более подробно о конфигурировании Unicorn можно узнать на официальном сайте и в огромном количестве источников в интернете, поэтому не будем уделять внимание данному файлу.
Мы лучше перейдем к самому главному - запуску!
Сделать это довольно просто. Зайдя в каталог с приложением, выполним команду:
# unicorn_rails -c config/unicorn.rb

Вместо заключения

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

Установка дополнительных библиотек для Ruby (RVM)

02 ноября 2011, 12:42
В посте про установку Ruby на Debian с использованием RVM, я упомянул про установку дополнительных библиотек для языка, таких как Zlib, OpenSSL и другие.

В недрах документации к RVM нашелся полный список дополнительных зависимостей, при установке которых версия Ruby будет сразу же скомпилирована с полным списком дополнительных библиотек.

Итак, перед установкой интерпретатора, на вашем сервере (VPS) необходимо выполнить команду:
# sudo apt-get install build-essential openssl libreadline6 libreadline6-dev curl git-core zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3 libxml2-dev libxslt-dev autoconf libc6-dev ncurses-dev automake libtool bison subversion

И заодно так можно решить проблему с установкой гема mysql2:
# sudo apt-get install libmysqlclient-dev

Удачи!

Вышел Ruby 1.9.3! Краткая инструкция по обновлению

31 октября 2011, 14:44
Спустя год разработки, наконец-то вышла в свет новая версия официального интерпретатора Ruby! Подробности можно почитать по вот этой ссылке, а затем обновиться :)

Если вы используете RVM, то сделать это довольно просто. Необходимо лишь выполнить команду:
# rvm get head && rvm reload
# rvm install 1.9.3

Либо, если вы хотите сохранить ранее установленные gem'ы, то вместо последней команды вызовите:
# rvm upgrade 1.9.2 1.9.3

Удачи!

Xen или OpenVZ?

13 октября 2011, 10:57
Несмотря на то, что технологии виртуализации появились уже достаточно давно, не все пользователи (и системные администраторы) успели вникнуть в принципиальные отличия между ними.

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

На первый взгляд может показаться, что технологии виртуализации OpenVZ (коммерческий ее вариант называется Virtuozzo) и Xen могут рассматриваться как конкурирующие платформы для услуги аренды VPS, однако в реальности они очень разные. Давайте наглядно опишем принцип их работы.

OpenVZ

OpenVZ – это реализация технологии виртуализации на уровне операционной системы, которая базируется на ядре Linux. Уже давнее время является лидером на рынке VPS хостинга. До появления Xen, существовало всего два варианта виртуализации: полностью виртуальный сервер (например, VMWare или VirtualBox) и разделение ресурсов в рамках одного сервера, что и делает OpenVZ.

Честная виртуализация работала неприемлемо медленно для VPS хостинга, поэтому для массовой услуги не годилась. Именно поэтому решения на базе OpenVZ полностью и заняли этот рынок.

Принцип работы OpenVZ
Рассмотрим, как это работает.

На хост-машине работает специально модифицированное ядро Linux, отвечающее за распределение ресурсов между выполняющимися на ней VPS. Ядро отвечает за изоляцию файловой системы, оперативной памяти и процессов между виртуальными окружениями (так называются VPS в терминах OpenVZ), предоставляя администраторам VPS полный административный доступ к их серверу.

Как же разделяются ресурсы в системе OpenVZ? Хост-сервер ведет множество всевозможных счетчиков (помимо используемой мощности процессора, объема памяти и жесткого диска) и не дает их превышать.

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

Ядро OpenVZ, которое управляет всеми ресурсами, одно на всех. Поэтому ограничивать все-таки приходится.

Также, одно ядро означает, что его нельзя заменить. Отсюда вытекает вторая проблема — невозможно на арендованную VPS поставить другую операционную систему (например, FreeBSD или тем более Windows).

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

Аналогично, не имея своего ядра, нельзя загрузить в него нужный модуль или изменить системную настройку — нужно обязательно просить хостера (и надеяться, что он не ответит отказом). Файловая система тоже получается одна на всех. Если будет сбой, он коснется все виртуальные серверы на хост-машине. И создать себе отдельную файловую систему тоже нет возможности.

Самая же большая проблема, постоянно напоминающая о себе — это память. Ее ограничение работает не так, как в реальном сервере: нужный объем оперативной памяти имитируется через счетчики, и имитируется неполноценно. Поэтому любая программа, абсолютно непредсказуемо, может не запуститься — хотя она будет использовать не больше отведенного виртуальному окруженю предела, из-за неточной имитации ограничений, OpenVZ может ошибиться в подсчетах. Тогда придется увеличить тариф в два, а то и в три раза. Соответственно, хостеры решают эту проблему предоставлением (негарантированной) памяти больше, чем должно приходиться по тарифу (и суммарный ее объем – конечно же будет превышать количество оперативной памяти, установленной на хост-машине). В большинстве случаев это работает. До момента, когда некоторые VPS не начнут использовать отведенную им, пусть и негарантированную, память полностью. В этот момент остальным серверам ее уже может не хватить. Также немаловажно, что все виртуальные серверы используют один и тот же раздел подкачки. Поэтому решить описываемую проблему через дополнительный раздел подкачки тоже не получится.

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

Однако, у технологии OpenVZ есть неоспоримое преимущество — смена тарифа реализуется изменением лимитов на VPS через смену счетчиков. Никакой перезагрузки не требуется!

Согласно сайту OpenVZ, накладные расходы на виртуализацию также очень малы, и падение производительности составляет всего 1-3% по сравнению с обычными Linux-системами. Так как данная технология позволяет продавать ресурсов больше, чем реально есть, хостеры могут ощутимо снизить цену - отсюда понятно, почему цены на виртуальные серверы могут сильно отличаться. Не сложно догадаться, что зачастую это влечет и снижение качества услуги.

Xen

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


Каждая VPS получает только строго отведенную ей область оперативной памяти и работает с ней точно так же, как и на реальном сервере. Никаких проблем с имитацией ограничений и странных подсчетов.

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

Список поддерживаемых операционных систем очень широк. Можно производить установку ОС, начиная с загрузки BIOS. Это может быть Linux, FreeBSD, OpenSolaris, Windows или даже MS DOS.

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

Та часть Xen, которая исполняет все работающие ядра ОС имеет весьма небольшой размер. А чем проще — тем надежней.

Конечно, у этой технологии тоже есть свои недостатки – для миниальной потери производительности, устанавливаемая на арендованный виртуальные сервер ОС должна иметь поддержку запуска в Xen. К счастью, список таких ОС постоянно пополняется.

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

Установка Ruby и Ruby On Rails на Debian Linux

30 сентября 2011, 23:18
Как известно, дистрибутив Debian отличается своей стабильностью. А значит.. версии ПО (а конкретно ruby) в его репозиториях поражают своей актуальностью!
Самым популярным способом для продвинутого пользователя Linux будет установка интерпретатора ruby из исходных кодов. Однако есть способ более гибкий и интересный - использование RVM.

Что же это такое?

RVM расшифровывается как Ruby Version Manager. Средство управления версиями Ruby. Данная утилита позволит нам устанавливать на сервере различные версии интерпретаторов (от MRI 1.8 до REE) и удобным способом переключаться между ними. Также, RVM позволяет нам создавать gemset'ы - наборы gem'ов, установленные в отдельные каталоги и для каждого проекта переключаться между ними. Но данная функциональность нам не очень интересна, т.к. замечательный инструмент под названием bundler отлично справляется с задачей управления версиями gem'ов.

Варианты установки

Согласно документации, существует два способа установки RVM: однопользовательский (если мы являемся разработчиком и ставим ruby только для себя), либо многопользовательский - если мы разворачиваем сервер для хостинга Ruby On Rails приложений. Именно о последнем способе мы и будем вести речь. На самом деле, разница невелика :-)

Подготовка системы

Первым делом необходимо установить дополнительные пакеты. Среди них и компилятор gcc, потому что RVM будет собирать ruby из исходных кодов.
В Debian (и соответственно в Ubuntu) подобные приготовления провести довольно просто, разработчики дистрибутива о нас уже позаботились.
Просто выполним команду:
# sudo apt-get install build-essential

Следующим шагом необходимо установить Git и curl. Именно с их помощью и будут скачиваться исходники.
# sudo apt-get install git curl

Установка RVM

Прочитав по-диагонали мануал с официального сайта, находим магическую команду установки, которую нам необходимо выполнить (обязательно под пользователем root или через sudo):
# sudo bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)

Самое интересное

Итак, RVM должен быть успешно установлен в нашей системе. Давайте в этом убедимся и заодно порадуемся списку поддерживаемых версий интерпретатора:
# rvm list known

Ого! Впечатляет? На данный момент самым популярным выбором будет установка версии 1.8.7 (да, с выходом Rails 3.1 можно потихоньку переходить на 1.9.2). Чтож, приступим.
Для начала необходимо доустановить в систему дополнительные (опциональные) библиотеки, которые могут быть использованы самим ruby и его отдельными gem'ами. Например это zlib.
# sudo apt-get install zlib1g-dev

И собственно приступаем к установке ruby (из-под пользователя root; sudo в данном случае не сработает):
# rvm install ruby-1.8.7

Смотрим и наслаждаемся процессом. На наших VPS установка занимает всего несколько минут :-)

Установка дополнительных библиотек

Хочу с вами поделиться важным знанием, о котором тяжело найти упоминание в инструкциях по установке Ruby и/или RVM.
При компиляции ruby, инсталлятор проверяет найденные в системе библиотеки и устанавливает обертки для них. Например это упомянутый ранее zlib, curses, openssl. К слову сказать, без первой не будет работать так горячо любимый нами bundler.
Итак, важное знание заключается в том, что в любой момент мы можем легко доустановить обертки для любой из забытых нами библиотек! Для этого нам необходимо сначала из репозиториев установить -dev версию библиотеки (для zlib это zlib1g-dev), затем зайти в подкаталог ext исходных кодов интерпретатора и выполнить пару несложных команд.
Вот как это выглядит для установки zlib для ruby-1.8.7:
# sudo apt-get install zlib1g-dev
# cd /usr/local/rvm/src/ruby-1.8.7-p352/ext
# cd zlib
# ruby extconf.rb
# make && make install

Bundler, Rails и сотоварищи

Для того, чтобы использовать установленную версию интерпретатора, необходимо дать соответствующую команду RVM'у:
# rvm use 1.8.7

Данная команда выберет версию 1.8.7 и дальнейшие вызовы ruby, gem - будут использовать данную версию интерпретатора. И можно приступать к установке дополнительных гемов:
# gem install bundler rails

В завершении стоит отметить, что для запуска проектов на Ruby On Rails может понадобиться использовать такую команду:
# /usr/local/rvm/bin/rvm 1.8.7 exec ruby script/server

Ведь на самом деле команда rvm - это дополнительная функция в шелле пользователя. В некоторых случаях она не доступна и необходимо напрямую использовать исполняемый файл rvm.
Надеюсь, статья оказалась полезной :-) Если есть какие-то вопросы - обязательно пишите! С радостью пообщаемся.

Ruby On Rails

27 сентября 2011, 21:27

Почему появился этот пост в нашем блоге? Зачем мы создали отдельную категорию под названием ruby on rails?

Просто мы очень любим этот замечательный фреймворк и язык, на котором он основан :-)

Может быть кто-то еще не заметил: абсолютно все наши сайты написаны с использованием этой классной системы. Если вы веб-разработчик и еще не знакомы с RoR, то вам сюда: http://rubyonrails.org/

Обновление почтовой системы

27 сентября 2011, 13:19
Мы постоянно совершенствуемся, растем и стараемся повысить эффективность нашей платформы. На этот раз обновлению подлежит почтовая подсистема - сервисы IMAP/SMTP, а также веб-интерфейс доступа к почте. Мы постараемся все основные работы проводить в ночное время, чтобы вы не заметили перебоев в работе. А на время работ вся входящая электронная почта будет перенаправлена на резервный сервер, чтобы ни одно, даже самое маленькое сообщение, не было потеряно!