Доброго времени суток, user.
Не так давно у меня возникла задача сделать прототип для одного проекта. В него входила работа с Facebook Graph API. Поковыряв некоторые гемы, я понял, что они для меня не совсем удобные или же реализуют нужный функционал уж слишком сложно. И тут в моей голове всплыла старая идея о написании своего гема. Загуглив массу запросов по этой теме, не нашел полной информации, тем более на русскоязычных ресурсах. Вот так и возникла идея этой статьи. Руководство названо «почти полным», так как тут освещены не все аспекты, а лишь те, которые минимально необходимы и желательны для начала существования продукта вашего воображения. Прошу под кат!
Начнем с базового (спасибо Википедии):
RubyGems (от англ. gem, gems— драгоценный камень) — система управления пакетами для языка программирования Руби который предоставляет стандартный формат для программ и библиотек Руби (в самодостаточном формате «gems»), инструменты, предназначенные для простого управления установкой «gems», и сервер для их распространения.
NOTE: Прошу учесть, что именно RubyGems, а не RailsGems или RoRGems!!! Это значит, что гемы пишутся непосредственно на чистом и блестящем Ruby, а то, что помечено как Rails Gem — всего лишь Ruby Gem, но использующий, либо дополняющий Rails (кстати, кто не в курсе, Rails — тоже Ruby Gem).
Я использую для разработки IDE от JetBrains — RubyMine (v6.3). В основном из-за удобного autocomplete и интеграции с Git, SFTP и других плюшек. Поэтому все махинации буду показывать именно в этой IDE. Для приверженцев Sublime/Vim/Emacs + Terminal есть куча инструкций по генерации gem-темплейтов через консоль.
Итак, начнем.
Я являюсь создателем, пускай пока сыроватого, но функционирующего гема Fobos (current v0.0.6). Все познания я взял из процесса его разработки.
Шаг 1: Создание болванки
В RubyMine это выглядит как создание нового проекта, но с выбором Poject Type: Ruby Gem.
Далее будет выбор версии Ruby. Что, в принципе, ясно и не требует объяснения.
В итоге получаем проект с такой структурой (я убрал галочки для создания bin и test директорий).
Рассмотрим по порядку всю структуру.
- lib — непосредственно хранит весь код (ну или почти весь) вашего приложения;
- .gitignore — хранит список файлов и папок, которые не должны попасть под контроль версий (файлы бд, скомпилированные ассеты, логи и т.п.);
- Gemfile, Gemfile.lock — список других гемов, которые вы используете для работы или при разработке изображения. Но в случае гема они недоступны, т.к. они указываются в файлу *.gemspec;
- LICENSE.txt — хранит лицензию использования. В моем случае — это MIT;
- Rakefile — хранит Rake таски. Подробнее можно легко найти в интернете;
- REAMDE,md — «лицо» вашего приложения. Выводится на стартовых страницах GitHub и RubyDoc;
- SomeCoolGem.gemspec — некоторый манифест, в котором хранится основная информация и зависимости приложения.
Шаг 2: создание структуры для работы приложения
Теперь будем работать непосредственно с директорией lib.
Файл SomeCoolGem.rb является стартовым. По идее в нем должна храниться вся логика, но, как показывает практика, гораздо целесообразней создать модуль и разделить приложение на классы по функциональности, а затем просто подгружать их в этот файл. Для тех, кто знаком с языками C++/Java/C# — этот файл чем-то сродним методу main().
Сразу создадим модуль HelloWorld. И в нем создадим сласс Alloha.
Так как весь гем, по сути, есть модуль то уже в файле SomeCoolGem.rb будет следующий код:
require "SomeCoolGem/version"
module SomeCoolGem
# Your code goes here...
end
Вот так изменилась структура проекта:
Вот класс Alloha:
module SomeCoolGem
module HelloWorld
class Alloha
end
end
end
Шаг 3: Делаем нужный функционал
Добавим в класс Alloha поле, конструктор и какие-нибуль методы для демонстрации:
module SomeCoolGem
module HelloWorld
class Alloha
attr_accessor :name
def initialize(name)
@name = name
end
def generate_alloha
"Alloha, #{@name}, from SomeCoolGem!"
end
def say_alloha
puts generate_alloha
end
end
end
end
Шаг 4: Проверяем работоспобность
Так как гем — это модуль, то использовать мы его можем тоже как модуль. Для проверки я обычно использую IRB.
Вот пример:
2.1.2 :001 > load 'alloha.rb'
=> true
2.1.2 :002 > object = SomeCoolGem::HelloWorld::Alloha.new('User')
=> #<SomeCoolGem::HelloWorld::Alloha:0x00000000e7f950 @name="User">
2.1.2 :003 > object.generate_alloha
=> "Alloha, User, from SomeCoolGem!"
2.1.2 :004 > object.say_alloha
Alloha, User, from SomeCoolGem!
=> nil
2.1.2 :005 >
Как видим, мало чем отличается от работы обычно проекта. Грубо говоря, при использовании гема ваше приложение просто подключает модуль с вложенными модулями/классами и вы можете использовать их как и обычные модули/класссы Ruby.
Шаг 5: Подключаем все к главному файлу
Для этого нужно немного изменить наш стартовый файл SomeCoolGem.rb:
require "SomeCoolGem/version"
module SomeCoolGem
require 'SomeCoolGem/hello_world/alloha'
end
Теперь при указании нашего гема в Gemfile приложения мы сможем использовать его как обычный модуль Ruby.
Шаг 6: Сборка гема и его версионизация
В файле version.rb хранится текущая версия нашего гема:
module SomeCoolGem
VERSION = "0.0.1"
end
Перед каждым релизом нужно будет менять это значение.
Сразу скажу, что если вы делаете новый коммит, то не обязательно менять версию. Однако если меняется логика программы, то лучше сделать релиз.
Чтобы собрать версию гема, вам нужно выполнить команду:
gem build SomeCoolGem.gemspec
В корне проекта появится файл SomeCoolGem-0.0.1.gem.
Поздравляю. Первая версия гема собрана!
Шаг 7: Пушим гем
Подробная и свежая инструкция всегда лежит здесь.
Так же поный набор инструкций находится здесь.
Там все хорошо и подробно описано.
Шаг 8: Просветление
Теперь я бы хотел поговорить о некоторых плюшках, которые многим интересны.
1. Можно проапдейтить профиль гема на RubyGems. Там есть настройки, в которых можно добавить описание, линки и прочее.
2. Бейджи. Бейджи заслуживают отдельной небольшой темы. Но в двух словах — это обычные картинки, которые вы вешаются в ваш README файл. Они отображают статус пройденных тестов на различных сервисах. Например, проверка чистоты кода. Более подробно можно прочитать здесь.
3. README файл вы должны составлять сами. Старайтесь указывать, какие версии с какими совместимы или нет. Если были сделаны глобальные изменения или закрыта часть старого функционала, меняйте не минорную версию, а постарше, в зависимости от глобальности изменений.
4. Описывайте качественную документацию. Зачастую именно от нее зависит желание использовать вашу наработку или нет.
5. Старайтесь реализовывать функционал с минимальными зависимостями от других гемов и следите за тем, чтобы использовать новые версии в своих наработках.
На этом, пожалуй, все. Удачи всем тем, кто начинает свой путь в этом направлении. Буду рад критике и уточнениям.
Автор: mxgoncharov