Rails5 API

| rails rails5 rails-api json json-api

Bài viết này mình sẽ hướng dẫn tạo và setting cơ bản cho 1 Rails API app. Các config, setting trong bài viết này đều được tham khảo từ nhiều nguồn khác nhau :).

Setting về Rails

Bắt đầu bằng câu lệnh thân thương :D

rails new gooners-bot --api

Sửa Gemfile, thêm các gem cần thiết để deploy lên heroku và debug.

source 'https://rubygems.org'


# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.0.0', '>= 5.0.0.1'
# Use Puma as the app server
gem 'puma', '~> 3.0'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
# gem 'jbuilder', '~> 2.5'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 3.0'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'

# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development

# Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
gem 'rack-cors'

# "JsonApi Adapter" provided by this gem will save us a lot of time
gem 'active_model_serializers', '~> 0.10.0'

group :development, :test do
  # Use mysql as the database for Active Record
  gem 'mysql2', '>= 0.3.13', '< 0.5'
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platform: :mri
end

group :development do
  gem 'listen', '~> 3.0.5'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
  gem 'binding_of_caller'
  gem 'better_errors'
end

group :production do
  gem 'pg'
  gem 'rails_12factor'
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

Thêm group production để install gem cho heroku.

Tiếp đến là database.yml. Phần host có thể bạn cần phải đổi thành localhost. Mình sử dụng docker để build môi trường, nên sẽ hơi khác 1 chút.

default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: root
  password: pass
  host: mysql

development:
  <<: *default
  database: gooners-bot_development

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: gooners-bot_test

Không cần production vì mình sẽ deploy lên heroku, heroku sẽ tự động thay file database.yml.

Setting CORS

Trong Gemfile mình đã cho thêm rails-cors vào. Tiếp theo sẽ setting cho CORS.

Create file config/initializers/cors.rb

# Be sure to restart your server when you modify this file.

# Avoid CORS issues when API is called from the frontend app.
# Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin AJAX requests.

# Read more: https://github.com/cyu/rack-cors

Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins '*'

    resource '*',
      headers: :any,
      methods: [:get, :post, :put, :patch, :delete, :options, :head]
  end
end

Sử dụng Serializing API Output

Trong Gemfile ta đã thêm gem gem 'active_model_serializers', '~> 0.10.0', gem này hỗ trợ serializing API, 1 gem cực kì mạnh mẽ và cần thiết với các app sử dụng API.

github ActiveModelSerializers

Để setting cho serializer, ta tạo file config/initializers/active_model_serializer.rb

ActiveModelSerializers.config.adapter = :json_api

api_mime_types = %W(  
  application/vnd.api+json
  text/x-json
  application/json
)
Mime::Type.register 'application/vnd.api+json', :json, api_mime_types

Trong phần config adapter, có những adapter sau được hỗ trợ :

  • attributes
  • base
  • json_api
  • json
  • null

Ta có thể sử dụng command sau để tạo ra 1 serializer

rails g serializer user

Command này sẽ tạo ra file app/serializers/user_serializer.rb:

class UserSerializer < ActiveModel::Serializer
  attributes :id
end

JSON_API là 1 chuẩn mới rất mạnh mẽ và thú vị, nhưng cũng “làm khó” FE vì lượng thông tin lớn và phải xử lý nhiều. Ngoài JSON_API thì cũng có xu thế mới rất thú vị là GraphQL của Facebook.

Versions cho API

Một phần không thể thiếu của 1 API được thiết kế tốt là quản lý versions. Khi có version thì endpoint của API sẽ như sau :

GET http://api.mysite.com/v1/users/
# or
GET http://mysite.com/api/v1/users/

Cấu trúc thư mục code sẽ như sau :

app/controllers/
.
|-- api
|   `-- v1
|       |-- api_controller.rb
|       `-- users_controller.rb
|-- application_controller.rb

controllers sẽ giống như sau :

# app/controllers/api/v1/api_controller.rb

module Api::V1
  class ApiController < ApplicationController
    # Generic API stuff here
  end
end
# app/controllers/api/v1/users_controller.rb

module Api::V1
  class UsersController < ApiController

    # GET /v1/users
    def index
      render json: User.all
    end

  end
end

Tiếp theo là config routes

constraints subdomain: 'api' do
  scope module: 'api' do
    namespace :v1 do
      resources :users
    end
  end
end

Hoặc config cho /api/v1/users:

  namespace :api do
    namespace :v1 do
      resources :users
    end
  end

Advanced : rails-attack

rails-attack rails-attack là 1 gem bảo vệ API của bạn trước DDoS, brute force attacks, hammering, hoặc đơn giản là để hạn chế sử dụng.

Để setting gem này cần 1 chút thời gian để tìm hiểu.

Trong bài viết sau chúng ta sẽ tìm hiểu về token, auth, và các thứ khác liên quan đến users :).

Comments