...

пятница, 26 сентября 2014 г.

Grape: не рельсами едиными



В этом посте я хотел бы познакомить вас с Grape — веб-фреймворком, написанным на ruby, предназначенным для быстрой и удобной разработки API, а также немного порассуждать о судьбе Rails в свете последних тенденций в веб-разработке.


Ruby = Ruby On Rails




Как-то так сложилось, что при упоминании ruby в качестве средства веб-разработки (да и просто в качестве скриптового ЯП) передо многими людьми, имеющими некоторое отношение к этой самой веб-разработке, в голове возникает если не логотип с пресловутыми белыми рельсами на красном фоне, то магическое словосочетание Ruby On Rails уж точно.

Я не берусь спорить, хорошо это или плохо — эта статья не для спора. Одно могу сказать с уверенностью — RoR оказал огромное влияние на развитие веб-фреймворков в целом, а этот вклад переоценить крайне трудно.

НО




Но жизнь не стоит на месте.

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

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

AngularJS, Ember, Meteor.js, Derby.js — технологии, предвосхищающие очередной прорыв в сайтостроении, который можно сравнить с «изобретением» AJAX в старые добрые времена.

Ruby-разработчикам нужно мощное и в то же время легкое для освоения средство для разработки API, которым когда-то стали RoR для обычных сайтов.

Давайте уже к делу!




Действительно, хватит рассуждений. Встречайте — Grape

Это фреймворк, заточенный под разработку API, никаких швейцарских ножей.

Но надо отдать должное, он умеет делать API очень неплохо.

Попробую перечислить основные его достоинства:


  1. DSL, заточенный под описание API

  2. версионирование API из коробки

  3. параметризация методов со встроенной валидацией

  4. автоматическая генерация OPTIONS (кто встречался с CORS — оценит)

  5. прозрачная работа с форматами API

  6. встроенный DSL для документирования




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

Code time




Для начала приведу пример простого приложения, которое по адресу /hello/world.json вернет нам {hello: 'world'}

Gemfile



source 'https://rubygems.org'

gem 'grape', github: 'intridea/grape'
gem 'rack', '~> 1.5.2'
gem 'thin', '~> 1.6.2'


hello_world.rb



require 'grape'

class HelloWorld < Grape::API
format :json
namespace :hello do
get :world do
{hello: 'world'}
end
end
end


config.ru



require_relative 'hello_world'

run HelloWorld


На моем i5 c 16 Гб памяти и HDD это приложение стартует где-то за 400-700 мс. Вот список используемых гемов:



Using i18n 0.6.11
Using json 1.8.1
Using minitest 5.4.1
Using thread_safe 0.3.4
Using tzinfo 1.2.2
Using activesupport 4.1.6
Using descendants_tracker 0.0.4
Using ice_nine 0.11.0
Using axiom-types 0.1.1
Using builder 3.2.2
Using coercible 1.0.0
Using daemons 1.1.9
Using equalizer 0.0.9
Using eventmachine 1.0.3
Using hashie 3.3.1
Using multi_json 1.10.1
Using multi_xml 0.5.5
Using rack 1.5.2
Using rack-accept 0.4.5
Using rack-mount 0.8.3
Using virtus 1.0.3
Using grape 0.9.1 from git://github.com/intridea/grape.git (at master)
Using thin 1.6.2




Как вы могли заметить, в Grape есть чудесная штука, которая называется namespace. Она же group, resource, resources, segment — все для удобства чтения кода.

При этом она может использоваться без параметров. Казалось бы, зачем? А вот вам пример:

namespace :authorized do
before { authorize! }
get :some_secret_data ...
end
group do
before { authorize! }
get :some_secret_data ...
end




Это как в фильме — «все что случилось в Лас-Вегасе — остается в Лас-Вегасе».

Внутри групп, равно как нэймспейсов, вы можете определять before и after блоки, которые будут выполняться только для роутов, указанных в данных группах (и глубже).

Вот пример, демонстрирующий использование параметров:



params do
requires :first_name, type: String
requires :last_name, type: String
optional :birth_date, type: DateTime
end
post :register do
...
end




Как по мне, так понятно без слов. Управление в роут даже не попадет, если с запросом не будут переданы параметры, которые удовлетворяют описанным условиям. Самое чудесное, что это все с минимальными модификациями можно использовать для документирования API. Например:

desc 'User signup'
params do
requires :first_name, type: String, desc: 'First name'
requires :last_name, type: String, desc: 'Last name'
optional :birth_date, type: DateTime, desc: 'Date of birth'
end
post :register do
...
end




Убиваем сразу целую охапку зайцев — код документирован на месте, подключив grape-swagger получаем swagger-совместимую документацию. Изменили код — изменилась документация.

Одной из многих чудесных штук, которые меня покорили в Grape, является mount. Позволяет примонтировать ранее описанный API в новое место:


mount.rb



class Mount < Grape::API
get :mounted do
{mounted: true}
end
end




mount.rb

require 'grape'
require_relative 'mount'
class HelloWorld < Grape::API
format :json
namespace :hello do
mount Mount
get :world do
{hello: 'world'}
end
end
end




Как мы все уже поняли, наш роут из класса Mount станет доступен по адресу /hello/mounted.json

«Меня терзают смутные сомнения...»




Само собой, объема среднестатистической статьи, которая не вызовет у хабражителя стойкого зевотного рефлекса, вряд ли хватит, чтобы рассказать о всех плюсах и минусах фреймворка. Моей задачей в первую очередь было вызвать в вас интерес — документация у проекта неплохая, трудностей с дальнейшим изучением возникнуть не должно.

Также на гитхаб-страничке можно найти перечень гемов, которые можно использовать совместно с grape.

Эпилог




До недавнего времени у проекта была небольшая проблема, связанная с автоматической перезагрузкой измененного кода в dev-режиме. Все Rails-разработчики к этому привыкли и на мой взгляд это must have feature. В issues на гитхабе эта проблема была озвучена несколько раз и вроде предлагались какие-то решения на Rack::Reloader и для случаев использования совместно с Rails.

Я позволю себе упомянуть свое собственное решение, которое увидело свет буквально пару недель назад, а именно гем grape-reload, предназначенный для использования в plain-rack стеках.

Для grape версии 0.9.0 и ранее можно использовать версию гема 0.0.3, для более поздних и master-ветки фреймворка используйте master-ветку репозитория гема.

Если вам будут интересны дальнейшие статьи, посвященные данному фреймворку — не забудьте упомянуть об этом в комемнтариях. Всем ruby, посоны!


This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий