Xây dựng một ứng dụng Restful API đơn giản với Rails 5 (Phần 1)

Giới thiệu

Sau một thời gian tìm hiểu về API trong Rails thì mình đã xây dựng được một ứng dụng đơn giản để có cái nhìn cơ bản về API. Và bài viết này nhằm mục đích ghi lại những gì mình đã tìm hiểu và làm được để ghi nhớ cho bản thân và chia sẻ cho các bạn mới bắt đầu với API.

Ở phần 1 này mình sẽ bắt đầu với việc xây dựng một ứng dụng CRUD để trả về dữ liệu dạng JSON để làm quen với cấu trúc Restful API. Ở phần 2 mình sẽ áp dụng Serializer để xây dựng các response cho ứng dụng, phần này mình sẽ viết ở bài sau.

Môi trường:

  • Ruby 2.5.1
  • Rails 5.2.4.1
  • MySQL

Bắt đầu

Khởi tạo project

rails new my_post_api --api -T

Cấu hình Gemfile

source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby "2.5.1"

gem "rails", "~> 5.2.4", ">= 5.2.4.1"
gem "mysql2"
gem "puma", "~> 3.11"

gem "bootsnap", ">= 1.1.0", require: false

group :development, :test do
  gem "byebug", platforms: [:mri, :mingw, :x64_mingw]
end

group :development do
  gem "listen", ">= 3.0.5", "< 3.2"
  gem "spring"
  gem "spring-watcher-listen", "~> 2.0.0"
end

gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby]

Sau đó chúng ta chạy lệnh bundle install để cài đặt các gem.

Cấu hình file config/database.yml

default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: root
  password: yourpassword
  socket: /var/run/mysqld/mysqld.sock

development:
  <<: *default
  database: my_post_api_dev

test:
  <<: *default
  database: my_post_api_test

production:
  <<: *default
  database: my_post_api_product

Sau khi đã cấu hình cho database chúng ta cần chạy lệnh rails db:create để tạo database.

Xây dựng model và controller

Tạo model

Chúng ta chạy lệnh sau để khởi tạo model Post cho project với 2 thuộc tính là title và content

rails g model Post title:string content:text

Sau đó chạy lệnh rails db:migrate để tạo bảng trong DB.

Thêm validation cho model Post để bắt lỗi nào.

# app/models/post.rb

class Post < ApplicationRecord
  validates :title, :content, presence: true
end

Bây giờ đã có model rồi, công việc tiếp theo đó là phải tạo dữ liệu mẫu để sử dụng. Ở đây mình sử dụng gem faker để seed dữ liệu.

Thêm gem faker vào Gemfile sau đó chạy bundle install.

[...]
group :development, :test do
  gem "byebug", platforms: [:mri, :mingw, :x64_mingw]
  gem "faker"
end
[...]

Thêm vào file db/seeds.rb để tạo dữ liệu mẫu.

5.times do
  Post.create(title: Faker::Book.title, content: Faker::Lorem.sentence)
end

Cuối cùng, chạy rails db:seed để import dữ liệu vào DB.

Route

config/route.rb

Rails.application.routes.draw do
  namespace :api do
    namespace :v1 do
      resources :posts
    end
  end
end

Tạo controller

Khởi tạo app/controllers/api_controller.rb. Controller này sẽ dùng ở phần 2 của bài viết này, nhưng mình khởi tạo sẵn để dùng.

class ApiController < ActionController::API
end

Tạo app/controllers/api/v1/posts_controller.rb

class Api::V1::PostsController < ApplicationController
  def index
  end
end

Xây dựng các phương thức cho controller

index

API này trả về danh sách tất cả các Post dưới dạng JSON

def index
    @posts = Post.order('created_at DESC')
    render json: {
      status: true,
      data: @posts
    }, 
    status: :ok
end

Bây giờ chúng ta chạy server với lệnh rails s để test API này với Postman

show

API này trả về 1 post tương ứng với id dưới dạng json

class Api::V1::PostsController < ApplicationController
  before_action :load_post, only: %i(show)

    [...]

  def show
    render json: {
      status: true,
      data: @post
    }, 
    status: :ok
  end

  private

  def load_post
    @post = Post.find_by id: params[:id]
    return if @post
    render json: {
      status: false,
      message: 'Not found'
    }, 
    status: :not_found
  end
end

Test với postman

Không tìm thấy record

create

API tạo record và lưu vào DB, sau đó trả về record đó dưới dạng JSON

class Api::V1::PostsController < ApplicationController
  before_action :load_post, only: %i(show)

   [...]

  def create
    @post = Post.new post_params
    if @post.save
      render json: {
        status: true,
        data: @post
      }, 
      status: :created
    else
      render json: {
        status: false,
        error: @post.errors
      }, 
      status: :unprocessable_entity
    end
  end

  private

  def post_params
    params.permit :title, :content
  end
  
 [...]
 
end

Để test với postman mình sẽ đổi lại type từ GET thành POST.

Ở tab Headers chúng ta sẽ thêm Key: Content-TypeValue: application/json

Ở tab Body ta thêm data để test:

{
	"title": "Test post title",
    "content": "Test post content"
}

update

API cập nhật record tương ứng với id

class Api::V1::PostsController < ApplicationController
  before_action :load_post, only: %i(show update)
  
  [...]
  
  def update
    if @post.update_attributes post_params
      render json: {
        status: true,
        data: @post
      }, 
      status: :ok
    else
      render json: {
        status: false,
        error: @post.errors
      }, 
      status: :unprocessable_entity
    end
  end
  
  [...]
  
 end

Để test phương thức update phần data sẽ tương tự như create, chỉ đổi method POST thánh PUT

delete

API xóa 1 record tương ứng với id ra khỏi DB

class Api::V1::PostsController < ApplicationController
  before_action :load_post, only: %i(show update destroy)
  
  [...]
  
  def destroy
    @post.destroy
    render json: {
      status: true,
      data: @post
    }, 
    status: :ok
  end
  
  [...]
  
 end

Chúng ta đổi method thành DELETE để test với postman

Tổng kết

Như vậy là mình đã tạo xong 1 RESTful API cơ bản rồi. Hi vọng qua bài viết này thì các bạn có thể nắm được cách tạo ra một ứng dụng API đơn giản. Ở bài viết tiếp theo chúng ta sẽ sử dụng Serializer để tạo response format thay vì viết riêng cho từng action như hiện tại.

Hẹn các bạn ở bài viết sau!


All Rights Reserved