Ruby on Rails API with Vue.js - Configuring Rails - 02
Bài đăng này đã không được cập nhật trong 6 năm
Back-end
Back-end của chúng ta sẽ là một ứng dụng Rails được lược bỏ phần view. Rails cung cấp chế độ "api" một cách tiện lợi bằng cách thêm flash --api khi chạy lệnh tạo ứng dụng mới.
Tạo ứng dụng với chế độ API
$ rails new recordstore-back --api
Thêm Gems
- Bỏ comment rack-cors và bcrypt
- Thêm redis và jwt_sessions
- Chạy lệnh bundle install
Gem file ở hiện tại sẽ như này:
# Gemfile - Jan 2019
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby '2.5.3'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.2.2'
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
# Use Puma as the app server
gem 'puma', '~> 3.11'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
# gem 'jbuilder', '~> 2.5'
# Use ActiveModel has_secure_password
gem 'bcrypt', '~> 3.1.7'
# Use ActiveStorage variant
# gem 'mini_magick', '~> 4.8'
# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development
# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', '>= 1.1.0', require: false
# Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
gem 'rack-cors'
gem 'redis', '~> 4.1'
gem 'jwt_sessions', '~> 2.3'
group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
end
group :development do
  gem 'listen', '>= 3.0.5', '< 3.2'
  # 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'
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
Tạo User model
Như đã nói ở bài trước, chúng ta sẽ không sử dụng gem Devise, Rails có một số tích hợp tiện dụng khác cho việc thiết lập xác thực người dùng (authentication). Gem Devise có vẻ khá phổ biến và dù sao chúng ta cũng đang tìm hiểu công nghệ, tại sao chúng ta không thử thêm các loại gem khác hoạt động tương tự Devise, nhỉ? 

Để đơn giản, chúng ta sẽ tạo User model chưa có quan hệ với Record hoặc Artist. Những quan hệ này sẽ được thêm vào sau để User có thể tương tác (thêm, sửa, xóa) Artist và Record trên ứng dụng với giao diện front-end.
$ rails g model User email:string password_digest:string
Trường password_digest sẽ sử dụng gem bcrypt mà chúng ta đã bỏ comment trong quá trình thiết lập ban đầu. Nó tạo ra một phiên bản token của mật khẩu để bảo mật tốt hơn.
Chúng ta cần phải sửa đổi migration file để các trường email và password_digest mặc định không thể null.
# db/migrate/20190105164640_create_users.rb
class CreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t|
      t.string :email, null: false
      t.string :password_digest, null: false
      t.timestamps
    end
  end
end
Chạy lệnh migrate:
$ rails db:migrate
Tạo Artist model
Model Artist sẽ có quan hệ has_many đối với mỗi Record (sẽ tạo ở dưới)
$ rails g scaffold Artist name
Thông thường khi chạy scaffold, Rails sẽ tự động sinh tất cả các thứ cần có để có thể tương tác ngay với một model: model, controller, view... nhưng ở đây Rails không sinh ra view, điều này xảy ra là do API-mode đang hoạt động đấy.
Tạo Record model
Record sẽ có thêm vài trường so với Artist, belongs_to Artist và User
$ rails g scaffold Record title year artist:references user:references
Chạy lệnh migrate:
$ rails db:migrate
Namespacing API
Tiếp theo, chúng ta cần làm việc với routing. APIs thường thay đổi, xu hướng chung là giới thiệu các phiên bản, cho phép bên thứ ba chọn phiên bản API mới nếu họ thấy phù hợp. Điều này giúp ít lỗi hơn cho mọi người nhưng đi kèm với việc bạn phải thiết lập back-end, chủ yếu liên quan đến routing và vị trí tệp.
Để namespace ứng dụng với phiên bản đầu tiên, chúng ta cần sửa lại ở routing:
# /config/routes.rb
Rails.application.routes.draw do
  namespace :api do
    namespace :v1 do
     # routes go here
    end
  end
end
Update routes
Tiếp theo, chúng ta cần thêm các resources bên trong các namespace
# /config/routes.rb
Rails.application.routes.draw do
  namespace :api do
    namespace :v1 do
      resources :artists
      resources :records
    end
  end
end
Sau khi cập nhật routes.rb, chúng ta cũng cần đặt controllers về đúng vị trí: di chuyển artistscontroller.rb và recordscontroller.rb vào thư mục trong đường dẫn app/controllers/api/v1/ ... Hãy chắn chắn bạn đã sửa cả hai, sau đấy restart lại server nếu nó vẫn đang chạy.
Dưới đây là artists controller:
# app/controllers/api/v1/artists_controller.rb
module Api
  module V1
    class ArtistsController < ApplicationController
      before_action :set_artist, only: [:show, :update, :destroy]
      def index
        @artists = Artist.all
        render json: @artists
      end
      def show
        render json: @artist
      end
      def create
        @artist = Artist.new(artist_params)
        if @artist.save
          render json: @artist, status: :created
        else
          render json: @artist.errors, status: :unprocessable_entity
        end
      end
      def update
        if @artist.update(artist_params)
          render json: @artist
        else
          render json: @artist.errors, status: :unprocessable_entity
        end
      end
      def destroy
        @artist.destroy
      end
      private
      def set_artist
          @artist = Artist.find(params[:id])
      end
      def artist_params
          params.require(:artist).permit(:name)
      end
    end
  end
end
Và records_controller.rb
module Api
  module V1
    class RecordsController < ApplicationController
      before_action :set_record, only: [:show, :update, :destroy]
      def index
        @records = current_user.records.all
        render json: @records
      end
      def show
        render json: @record
      end
      def create
        @record = current_user.records.build(record_params)
        if @record.save
          render json: @record, status: :created
        else
          render json: @record.errors, status: :unprocessable_entity
        end
      end
      def update
        if @record.update(record_params)
          render json: @record
        else
          render json: @record.errors, status: :unprocessable_entity
        end
      end
      def destroy
        @record.destroy
      end
      private
      def set_record
        @record = current_user.records.find(params[:id])
      end
      def record_params
        params.require(:record).permit(:title, :year, :artist_id)
      end
    end
  end
end
Như vậy chúng ta đã config cơ bản các model, routing, controller cho back-end, vẫn còn khá đơn giản và không có gì mới ngoài Rails nhỉ? 
 Phần sau mình sẽ thiết lập xác thực người dùng sử dụng JWT_Sessions nhé, phần này đến đây thôi.
 Phần sau mình sẽ thiết lập xác thực người dùng sử dụng JWT_Sessions nhé, phần này đến đây thôi. 
Sayonara!! (。◡﹏◡。)
Nguồn tham khảo
All rights reserved
 
  
 