Антон Рябов bio photo

Антон Рябов

Не люблю бриться и у меня умный взгляд.

Email Twitter Telegram Github PGP RSS

Микросервисы сейчас очень популярны и используются в различных архитектурах и средах. Слова Ruby и микросервисы, принято связывать с великолепным минималистичным фреймворком Sinatra.

Есть много хороших Ruby микро-фреймворков, но Grape вместе с Swagger UI через гем swagger действительно крут как быстрое, чистое и законченное решение. С Grape + Swagger UI мы можем создавать Restful API сервис при этом имея автоматически сгенерированный GUI для тестов и отладки API.

Обзор



От переводчика: Оригинал статьи

Пример микросервиса с Grape и Swagger

В качестве примера в данной статье мы создадим микросервис который предоставляет Restful CRUD ресурс - заметки.

От переводчика: на этом этапе вы должны знать или хотя бы понимать что такое REST, CRUD и API

Модель Note будет содержать:

  • author
  • title
  • content
  • summary
  • timestamps

API будет предоставлять классические CRUD действия:

  • create
  • read
  • update
  • delete
  • list

Весь код доступен в публичном репозитории.

Базовая структура приложения

На данном этапе структура и содержание проекта должны соответствовать коммиту - 20040af

├── app
│   └── core.rb
├── config.ru
├── Gemfile
└── Procfile

Мы будем использовать bundle для управления гемами и foreman для запуска приложения через команду foreman start. Файл config.ru будет подтягивать rubygems, bundle, core.rb и запускать приложение. core.rb в основном будет тянуть файлы нашего приложения: апи, модели и т.д.

Добавляем Grape и первый экшн

На данном этапе структура и содержание проекта должны соответствовать коммиту - 158fc4b


Grape - это REST-like API микро-фреймворк на Ruby. Он спроектирован так, что его можно запустить на Rack или добавить в существующее приложение на Rails или Sinatra. Предоставляет простой DSL для легкой разработки.

В качестве первого шага мы должны добавить grape гем и подключить его в нашем config.ru. Затем добавим каталог api с файлом ресурса api/notes.rb и экшеном /test. Также ./app/api/notes должно быть подключено в файле config.ru.

В файле api/notes.rb используется Grape DSL:

  version 'v1', using: :header, vendor: 'tonymadbrain'
    format :json

  resource 'notes' do

    get '/test' do
      { data: "TEST" }
    end
  end

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

foreman start

От переводчика: если у вас не установлен foreman необходимо выполнить команду gem install foreman

и откроем в браузере ссылку http://localhost:5000/notes/test. Мы должны увидеть следующее содержимое:

{“data”:”TEST”}

Добавляем Swagger и запускаем его через Rack

На данном этапе структура и содержание проекта должны соответствовать коммиту - 8b9ec95


Swagger - это простое и мощное представление RESTful API, включение его как сервиса может дать вам бесплатную интерактивную документацию, клиентский SDK и понятность. В нашем приложении мы хотим добавить swagger-ui - чистый html5 интерфейс для нашего API.

Сначала добавим гем grape-swagger который включает swagger для наших ресурсов. Добавим swagger документацию в app/api/notes.rb:

add_swagger_documentation \
  :info => {
     :title => "Notes API"
    },
   :hide_documentation_path => true,
   :mount_path => "/swagger_doc",
   :markdown => false,
   :api_version => 'v1'

Затем, скачаем swagger-ui в новый каталог public. Теперь нам нужно сервить /public/swagger-ui, для этого добавим гем rack-fiber_pool и добавим конфигурацию в config.ru:

use Rack::Static,
  :urls => ["/images", "/lib", "/js", "/css"],
  :root => "public/swagger_ui"

map '/swagger-ui' do
  run lambda { |env|
    [
      200,
      {
        'Content-Type'  => 'txt-html',
        'Cache-Control' => 'public, max-age=86400'
      },
      File.open('public/swagger_ui/index.html', File::RDONLY)
    ]
  }
end

В итоге проверяем API уже со Swagger по ссылке http://localhost:5000/swagger-ui



Добавляем ActiveRecord, создаем таблицу и модель

ActiveRecord и его rake задачи

На данном этапе структура и содержание проекта должны соответствовать коммиту - 412226f


Для добавления ActiveRecord в наше приложение мы можем использовать гем grape-activerecord. Итак, вначале добавим rake, mysql2 и grape-activerecord гемы в наш Gemfile. После установки можем настроить подключение к базе данных. Простой способ добавить добрый старый config/database.yml.

Затем мы должны включить менеджер подключений ActiveRecord добавлением строки в config.ru:

use ActiveRecord::ConnectionAdapters::ConnectionManagement

Добавление следующего Rake файла даст нам возможность использовать задачи базы данных:

require "bundler/setup"
require "grape/activerecord/rake"
namespace :db do
  # Some db tasks require your app code to be loaded, or at least your gems
  task :environment do
    require_relative "app/core"
  end
end

Запустим bundle exec rake -T и увидим все доступные задачи.

Таблица и создание моделей

На данном этапе структура и содержание проекта должны соответствовать коммиту - 8cc1a84


Давайте создадим базу данных:

bundle exec rake db:create

Теперь миграции:

bundle exec rake db:create_migration NAME=create_table_notes
class CreateTableNotes < ActiveRecord::Migration
  def change
    create_table :notes do |t|
      t.string :author
      t.string :title
      t.text :content
      t.text :summary
      t.boolean :private, default: false
      t.integer :valuation

      t.timestamps null: false
    end
    add_index :notes, :author
  end
end

Теперь мы можем добавить нашу простую ActiveRecord модель Note в файле app/models/note.rb.

class Note < ActiveRecord::Base
  validates :author, :title, :content, presence: true
end

Добавляем Restful CRUD экшены в наш ресурс

На данном этапе структура и содержание проекта должны соответствовать коммиту - c4d1cdf


И, наконец, пришло время чтобы кодить наши CRUD экшены, методы desc и params передают swagger UI описание экшена и опциональные параметры с их типами и описаниями.

Создаем экшены с документацией и логикой:

desc 'Create a note.'
params do
  requires :author, type: String, desc: 'Author'
  requires :title, type: String, desc: 'Title'
  requires :content, type: String, desc: 'Body'
  optional :summary, type: String, desc: 'Summary'
  optional :private, type: Boolean, desc: 'Private'
  optional :valuation, type: Integer, desc: 'Valuation'
end
post '/' do
  Note.create params
end

Swagger UI теперь должен показывать все экшены,





Заключение

В действительности этот пример очень простой, но он показывает как легко можно создавать микросервисы с документированным API на Ruby с помощью Grape и Swager.

Дополнительный бонус от использования Swagger это поддержка многих языков и фреймворков, мы получаем унифицированную документацию и UI для сервисов написанных на Java, Ruby, Python и т.д.

От переводчика: В некоторых моментах я не согласен с автором, например в оригинале используется каталог app/apis, у меня же app/api; использование foreman и activerecord избыточно; отсутсвует TDD и др.

#Ruby #REST #API #Tutorial #TechAndDev