Grape Rails.
Grape - это API-фреймворк для Ruby. Grape создан для работы с Rack приложениями. Для создания API используется простой DSL (domain specific language). Grape поддерживает разнообразные общепринятые практики при создании API.
Для установки, добавить в Gemfile:
gem 'grape'
или сразу "всё" необходимое для Rails
# grape
gem 'grape'
gem 'grape-entity'
# swagger
gem 'grape-swagger'
gem 'grape-swagger-entity'
gem 'grape-swagger-rails'
gem 'grape-swagger-representable'
Простой пример:
module Twitter
class API < Grape::API
version 'v1', using: :path
format :json
perfix :api
helpers do
def current_user
@current_user ||= User.authorize!(env)
end
def authenticate!
error!('401 Unautorized', 401) unless current_user
end
end
resource :statuces do
get :public_timeline do
Status.limit(20)
end
# GET --
desc 'Get status'
params do
requires :id, type: Integer, desc: 'Status ID'
end
route_param :id do
get do
Status.find(params[:id])
end
end
# POST --
desc 'Create'
params do
requires :status, type: String, desc: 'Status'
end
post do
authenticate!
Status.create({
user: current_user,
text: params[:status]
})
end
# PUT --
desc 'Update'
params do
requires :id, type: Integer, desc: 'ID'
requires :sttaus, type: String, desc: 'Status'
end
put :id do
authenticate!
current_user.statuses.find(params[:id]).update({
user: current_user,
text: params[:status]
})
end
# DELETE --
desc 'Delete'
params do
requires :id, type: Integer, desc: 'ID'
end
delete :id do
authenticate!
current_user.statuses.find(params[:id]).destroy
end
end
end
end
Grape копмилирует маршруты при первом запросе, но можно принудительно создать все маршруты API методом compile!
Twitter::API.compile!
Вызов можно добавить в config/application.rb
или в любой файл которые участвует в загрузке сервера.
# compile and pre-load
Twitter::API.compile!
run Twitter::API
Будут созданы маршруты
GET /api/v1/statuses/public_timeline
GET /api/v1/statuses/:id
POST /api/v1/statuses
PUT /api/v1/statuses/:id
DELETE /api/v1/statuses/:id
Grape автоматически отвечает HEAD и OPTIONS для всех GET запросов, и только OPTIONS для всех остальных.
Для использования с Rails (6.1) монтируем API в файле config/routes.rb
.
mount Twitter::API => '/'
Для поддержки имени класса API, добавить акроним в config/initializers/inflections.rb
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.acronym 'API'
end
API можно разбить на модули
class API < Grape::API
# сначала декларации и объявления
# затем уже монтирование модулей
mount Users::API
mount Products::API
mount Lagacy::API => '/legacy';
end
Параметры запроса доступны через Hash
params
. Включая GET, POST, PUT параметры и именованные параметры пути. Так же поддерживается multipart.
Rails Api
Для создания приложения
rails new my_api --api
Три основные вещи
- Приложение будет создано с минимальным набором промежуточных модулей чем обычное. В первую очередь не будут включены модули, которые отвечают за работу приложения в браузере (например поддержка
cookie
) ApplicationController
будет унаследован отActionController::API
вместоActionController::Base
.- Генераторы не будут создавать шаблоны, помощники.
Add Grape
- config/application.rb
- config/initializers/swagger.rb
- config/routes.rb
- app/assets/manifest/config.js
- config/initializers/cors.rb
Чтобы Swagger работал потребуется добавить вconfig/application.rb
require "sprockets/railtie"
. При создании приложения вapi mode
, эта функция отключена.
На начальном этапе config/application.rb
может выглядеть примерно так:
# config/application.rb
require_relative "boot"
require "rails"
# Pick the frameworks you want:
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "active_storage/engine"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_mailbox/engine"
require "action_text/engine"
require "action_view/railtie"
require "action_cable/engine"
require "sprockets/railtie" # required by swagger
require "rails/test_unit/railtie"
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module FilimonApi
class Application < Rails::Application
config.load_defaults 6.1
config.api_only = true
end
end
Добавить акроним API
# config/initializers/inflections.rb
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.acronym 'API'
end
Настройки Swagger
# config/initializers/swagger.rb
GrapeSwaggerRails.options.url = '/api/v1/swagger_doc.json'
GrapeSwaggerRails.options.app_url = 'http://localhost:3000'
GrapeSwaggerRails.options.app_name = 'My API'
Swagger assets
// app/assets/config/manifest.js
//= link grape_swagger_rails/application.css
//= link grape_swagger_rails/application.js
CORS, можно настроить в соответствие с потребностями проекта
# config/initializers/cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins '*'
resource '*', headers: :any, methods: [:get, :post, :patch, :put]
end
end
Маршруты, например Swagger подключается в режиме разработки
Rails.application.routes.draw do
mount API => '/'
mount GrapeSwaggerRails::Engine => '/swagger' if Rails.env.development?
end
API
Создаем директорию app/api
и файл app/api/api.rb
, например
# app/api/api.rb
require 'grape-swagger'
class API < Grape::API
format :json
prefix :api
version 'v1', using: :path
# GET /api/v1
get do
{version: '1'}
end
# EXAMPLES
# /api/v1/users
resources :user do
# GET /api/v1/users
get do
User.all
end
# POST /api/v1/users
# <input name="user[email]" type="email">
# <input name="user[password]" type="password">
# <input name="user[file]" type="file">
params do
requires :user, type: Hash do
requires :email, type: String
requires :password, type: String
optional :avatar, type: File
end
end
post do
User.create!(params[:user])
end
end
# Swagger docs
add_swagger_documentation
end
Swagger будет доступен по адресу http://localhost:3000/swagger