Docker
参考
本記事では、web コンテナのポートを 80:3000 で実装している
rails API 実装
cors 設定
Gemfile
+ gem 'rack-cors'
config/initializers/cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins 'http://localhost:3000'
resource '*',
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head]
end
end
ログイン機能実装
devise を使用する
ライブラリインストール
Gemfile
gem 'devise'
gem 'devise_token_auth'
User 作成
bin/rails generate devise:install
bin/rails generate devise User
bin/rails generate devise_token_auth:install User auth
bin/rails db:migrate
メール認証設定
今回は使用しない。
config/envioroments/development.rb
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
認証周り実装
各種コントローラー作成
bin/rails g controller auth/registrations
bin/rails g controller auth/sessions
auth/registrations_controller.rb
class Auth::RegistrationsController < DeviseTokenAuth::RegistrationsController
private
def sign_up_params
params.permit(:email, :password, :password_confirmation, :name)
end
end
auth/sessions_controller.rb
class Auth::SessionsController < ApplicationController
def index
if current_api_v1_user
render json: { is_login: true, data: current_api_v1_user }
else
render json: { is_login: false, message: "ユーザーが存在しません" }
end
end
end
application_controller.rb
class ApplicationController < ActionController::API
include DeviseTokenAuth::Concerns::SetUserByToken
skip_before_action :verify_authenticity_token
helper_method :current_user, :user_signed_in?
end
config/routes.rb
Rails.application.routes.draw do
mount_devise_token_auth_for 'User', at: 'auth', controllers: {
registrations: 'auth/registrations'
}
namespace :auth do
resources :sessions, only: %i[index]
end
end
API 確認
ユーザ作成
curl -X POST http://localhost/auth -d '[name]=test&[email]=test@example.com&[password]=password&[password_confirmation]=password'
ユーザログイン
curl -X POST -v http://localhost/auth/sign_in -d '[email]=test@example.com&[password]=password'
会議室予約管理作成
リソース作成
bin/rails g scaffold Rooms name:string
bin/rails g scaffold Meetings user:references room:references start_at:datetime end_at:datetime
bin/rails db:migrate
config/routes.rb
resources :rooms
resources :meetings
curl で確認
会議室登録
curl -X POST -H "Content-Type: application/json" -d '{"room": {"name": "会議室A"}}' http://localhost/rooms
会議登録
curl -X POST -H "Content-Type: application/json" -d '{"meeting": {"user_id": "1", "room_id":"1", "start_at":"2024-01-01 10:00:00", "end_at": "2024-01-01 11:00:00"}}' http://localhost/meetings
リレーション整理
/rooms/:room_id/meetings
room_id で絞り込まれた meetings のレコードが返ってくるようにする
models/room.rb
class Room < ApplicationRecord
has_many :meetings
end
models/meeting.rb
class Meeting < ApplicationRecord
belongs_to :room
belongs_to :user
end
config/routes.rb
resources :rooms do
resources :meetings, only: [:index]
end
meeting_controller.rb
# GET /meetings
def index
- @meetings = Meeting.all
+ @meetings = Meeting.where(where_params)
render json: @meetings
end
...
# Only allow a list of trusted parameters through.
def meeting_params
params.require(:meeting).permit(:user_id, :room_id, :start_at, :end_at)
end
+ def where_params
+ params.permit(:room_id, :start_at, :end_at)
+ end
既にその日時で予約がとられている場合は予約できないようにする
meetings_controller.rb
class MeetingsController < ApplicationController
before_action :set_meeting, only: [:show, :update, :destroy]
# GET /meetings
def index
if where_params[:room_id].present?
@meetings = Meeting.where(room_id: where_params[:room_id])
else
@meetings = Meeting.all
end
if where_params[:start_at].present?
@meetings = @meeting.where(start_at: where_params[:start_at]...)
else
current_time = Time.zone.now
rounded_time = current_time.change(hour: 0, min: 0, sec: 0)
@meetings = @meetings.where(start_at: rounded_time...)
end
if where_params[:end_at].present?
@meetings = @meeting.where(start_at: ...where_params[:start_at])
end
render json: @meetings
end
# GET /meetings/1
def show
render json: @meeting
end
# POST /meetings
def create
@meeting = Meeting.new(meeting_params)
is_not_exists = Meeting.where(
"(start_at >= ? AND start_at < ?) OR (end_at > ? AND end_at <= ?)",
meeting_params[:start_at], meeting_params[:end_at], meeting_params[:start_at], meeting_params[:end_at]
).where(room_id: meeting_params[:room_id]).empty?
if is_not_exists && @meeting.save
render json: @meeting, status: :created, location: @meeting
else
render json: @meeting.errors, status: :unprocessable_entity
end
end
# PATCH/PUT /meetings/1
def update
if @meeting.update(meeting_params)
render json: @meeting
else
render json: @meeting.errors, status: :unprocessable_entity
end
end
# DELETE /meetings/1
def destroy
@meeting.destroy
end
private
# Use callbacks to share common setup or constraints between actions.
def set_meeting
@meeting = Meeting.find(params[:id])
end
# Only allow a list of trusted parameters through.
def meeting_params
params.require(:meeting).permit(:user_id, :room_id, :start_at, :end_at)
end
def where_params
params.permit(:room_id, :start_at, :end_at)
end
end