🕌
Rails API (Docker) の作成
個人サービスの作成 && 勉強の為に Rails の API サービスの作成をしました。
作成したサンプルはこちらです。
インストール用のDocker
以下のようなディレクトリ、ファイル構成でDocker用のファイルを作成します。
- docker
- Dockerfile
- entrypoint.sh
- docker-compose.yml
Dockerfile
FROM ruby:3.1
ENV TZ=Asia/Tokyo
ARG RUBYGEMS_VERSION=3.3.20
RUN apt update -qq && apt install -y postgresql-client
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN gem update --system ${RUBYGEMS_VERSION} && \
bundle install
COPY . /myapp
COPY docker/entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]
entrypoint.sh
#!/bin/bash
set -e
rm -f /myapp/tmp/pids/server.pid
exec "$@"
docker-compose.yml
version: "3.9"
services:
db:
image: postgres
volumes:
- ./tmp/db:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: password
web:
build:
context: .
dockerfile: ./docker/Dockerfile
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db
railsのインストールと起動
プロジェクト直下にGemfileとGemfile.lockを用意します。
(Gemfile.lockは空)
Gemfile
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby "3.1.2"
# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
gem "rails", "~> 7.0.4"
rails のインストールと起動を行います。
docker-compose build
docker-compose run web rails new . --force --no-deps --database=postgresql
※--api
オプションをつけると後のrails db:create
でエラーになる為、つけない形で一旦回避しています
db の設定を行います
config/database.yml
default: &default
adapter: postgresql
encoding: unicode
host: db
username: postgres
password: password
pool: 5
development:
<<: *default
database: myapp_development
test:
<<: *default
database: myapp_test
db の作成とrailsの起動を行います
docker-compose run web rails db:create
docker-compose up -d
起動確認
rails api の設定
config.api_only = true
の追加と、継承元をActionController::API
へ変更します。
app/controllers/application_controller.rb
class ApplicationController < ActionController::API
config.api_only = true
end
rails api の確認
api確認用のテーブル、モデル、コントローラー作成
rails g model regex title:string
rails g controller regexes
rake db:migrate
API用のパスの設定
config/routes.rb
Rails.application.routes.draw do
namespace 'api' do
namespace 'v1' do
resources :regexes
end
end
end
テストデータの投入
rails c
Regex.create(title:'title1')
Regex.create(title:'title2')
コントローラーの変更(指定した名前空間へ移動)
app/controllers/api/v1/regexes_controller.rb
module Api
module V1
class RegexesController < ApplicationController
before_action :set_regex, only: [:show, :update, :destroy]
def index
regexes = Regex.order(created_at: :desc)
render json: { status: 'SUCCESS', message: 'Loaded regexes', data: regexes }
end
def show
render json: { status: 'SUCCESS', message: 'Loaded the regex', data: @regex }
end
def create
regex = Regex.new(regex_params)
if regex.save
render json: { status: 'SUCCESS', data: regex }
else
render json: { status: 'ERROR', data: regex.errors }
end
end
def destroy
@regex.destroy
render json: { status: 'SUCCESS', message: 'Deleted the regex', data: @regex }
end
def update
if @regex.update(regex_params)
render json: { status: 'SUCCESS', message: 'Updated the regex', data: @regex }
else
render json: { status: 'SUCCESS', message: 'Not updated', data: @regex.errors }
end
end
private
def set_regex
@regex = Regex.find(params[:id])
end
def regex_params
params.require(:regex).permit(:title)
end
end
end
end
Postmanで以下のURLにGET
{
"status": "SUCCESS",
"message": "Loaded regexes",
"data": [
{
"id": 2,
"title": "title2",
"created_at": "2022-11-10T07:55:56.123Z",
"updated_at": "2022-11-10T07:55:56.123Z"
},
{
"id": 1,
"title": "title1",
"created_at": "2022-11-10T07:55:49.070Z",
"updated_at": "2022-11-10T07:55:49.070Z"
}
]
}
rails api のテスト(rspec)
factory_bot_rails と rspec を追加
Gemfile
group :development, :test do
gem 'factory_bot_rails'
gem 'rspec-rails'
end
rspec の初期設定
bin/rails generate rspec:install
rspec のファイル生成コマンド
bin/rails g rspec:controller regexes
テストファイルを書き換える
spec/requests/api/v1/regexes_spec.rb
require 'rails_helper'
# logger
Rails.logger = Logger.new(STDOUT)
# SQL
# ActiveRecord::Base.logger = Logger.new($stdout) # SQLを出力
# ActiveRecord::Base.verbose_query_logs = true # SQLがコード上のどこで実行されたかを出力する
RSpec.describe "Regexes", type: :request do
it '全てのポストを取得する' do
FactoryBot.create_list(:regex, 10)
get '/api/v1/regexes'
json = JSON.parse(response.body)
# リクエスト成功を表す200が返ってきたか確認する。
expect(response.status).to eq(200)
# 正しい数のデータが返されたか確認する。
expect(json['data'].length).to eq(10)
end
end
rspec 実行
bundle exec rspec
Discussion