初めに
Ruby on rails を勉強するためにまずは簡単なアプリを作ろうと思う。
今回はTODOリストを作ってみる。
この記事を見た有識者の方へ
何か間違ってたらコメントください🙇♂️
構成
フロントエンド(React)
- Viteを使ってTypeScript対応のReactアプリを作成
- axios を使ってRails APIと通信
バックエンド(Rails API)
- postgreSQLを使用
- CRUDでAPI実装
- DBマイグレーションでDB作成したい
- Reactと通信できるようにCORS設定する
接続について
- RailsのCORS設定(フロントのローカルホストを許可)
- Reactでaxios.get('http://localhost:3000/tasks') してデータ取得
1. バックエンド(Rails API)構築
① Rails APIプロジェクトを作成
まず、RailsのAPIモードで新規プロジェクトを作成する。
コマンドプロンプト上で下記を実行
rails new todo-api --api -d postgresql
cd todo-api
② 必要なGemを追加
Gemfile を開いて、CORS設定用の rack-cors を追加(フロントと通信できるようにする)。
gem 'rack-cors'
下記を実行してインストール。
bundle install --gemfile
インストール後、config/initializers/cors.rb に設定を追加。
(※自分の環境ではコメントアウト状態になっていたのでそれを解除した)
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins 'http://localhost:5173' # Reactのローカル環境
resource '*', headers: :any, methods: [:get, :post, :put, :patch, :delete, :options]
end
end
③ データベースをセットアップ
まず、データベースを作成する。
rails db:create
④ Taskモデルを作成
以下のコマンドで Task モデルを作成する。
rails g model Task title:string completed:boolean
rails db:migrate
※自分の環境ではmigrateコマンド実行時にエラーが発生した。
下記のファイルを編集することでエラーが解消。
default: &default
adapter: postgresql
encoding: unicode
pool: 5
username: your_db_user
password: your_db_password
host: localhost
development:
<<: *default
database: todo_api_development
test:
<<: *default
database: todo_api_test
⑤ Controller とルーティングを設定
コントローラーを作成。
rails g controller Tasks
config/routes.rb にエンドポイントを追加
Rails.application.routes.draw do
resources :tasks
end
app/controllers/tasks_controller.rb を編集して、CRUDを実装
class TasksController < ApplicationController
before_action :set_task, only: [:show, :update, :destroy]
# GET /tasks
def index
tasks = Task.all
render json: tasks
end
# POST /tasks
def create
task = Task.new(task_params)
if task.save
render json: task, status: :created
else
render json: task.errors, status: :unprocessable_entity
end
end
# GET /tasks/:id
def show
render json: @task
end
# PATCH/PUT /tasks/:id
def update
if @task.update(task_params)
render json: @task
else
render json: @task.errors, status: :unprocessable_entity
end
end
# DELETE /tasks/:id
def destroy
@task.destroy
head :no_content
end
private
def set_task
@task = Task.find(params[:id])
end
def task_params
params.require(:task).permit(:title, :completed)
end
end
⑥ Railsサーバーを起動
rails s
これで http://localhost:3000/tasks にアクセスすると、空の配列 [] が返ってくる。
2. フロントエンド(React)構築
① Reactプロジェクトを作成
Viteを使ってTypeScript対応のReactアプリを作成する。
npm create vite@latest todo-frontend --template react-ts
cd todo-frontend
npm install
② 必要なライブラリをインストール
axios を使ってRails APIと通信する。
npm install axios
③ API通信用の関数を作成
src/api.ts を作成し、Rails APIと通信する関数を定義。
import axios from "axios";
const API_URL = "http://localhost:3000/tasks";
export const getTasks = async () => {
const res = await axios.get(API_URL);
return res.data;
};
export const addTask = async (title: string) => {
const res = await axios.post(API_URL, { title, completed: false });
return res.data;
};
export const updateTask = async (id: number, completed: boolean) => {
const res = await axios.patch(`${API_URL}/${id}`, { completed });
return res.data;
};
export const deleteTask = async (id: number) => {
await axios.delete(`${API_URL}/${id}`);
};
④ タスク一覧を表示
src/App.tsx にReactのコードを書く。
import { useState, useEffect } from "react";
import { getTasks, addTask, updateTask, deleteTask } from "./api";
type Task = {
id: number;
title: string;
completed: boolean;
};
function App() {
const [tasks, setTasks] = useState<Task[]>([]);
const [newTask, setNewTask] = useState("");
useEffect(() => {
fetchTasks();
}, []);
const fetchTasks = async () => {
const data = await getTasks();
setTasks(data);
};
const handleAddTask = async () => {
if (!newTask) return;
const task = await addTask(newTask);
setTasks([...tasks, task]);
setNewTask("");
};
const handleToggleTask = async (id: number, completed: boolean) => {
await updateTask(id, !completed);
setTasks(tasks.map(task => task.id === id ? { ...task, completed: !completed } : task));
};
const handleDeleteTask = async (id: number) => {
await deleteTask(id);
setTasks(tasks.filter(task => task.id !== id));
};
return (
<div>
<h1>TODO List</h1>
<input
type="text"
value={newTask}
onChange={(e) => setNewTask(e.target.value)}
/>
<button onClick={handleAddTask}>Add Task</button>
<ul>
{tasks.map((task) => (
<li key={task.id}>
<input
type="checkbox"
checked={task.completed}
onChange={() => handleToggleTask(task.id, task.completed)}
/>
{task.title}
<button onClick={() => handleDeleteTask(task.id)}>Delete</button>
</li>
))}
</ul>
</div>
);
}
export default App;
3. アプリを起動
① Rails API(バックエンド)を起動
rails s
② React(フロントエンド)を起動
npm run dev
③ 動作確認
- ブラウザで http://localhost:5173 にアクセス
- タスクを追加・削除・更新できるかチェック
下記のような画面が表示されればOK
課題
- UIがしょぼいので強化したい
- 認証機能を追加してもいいかも
- AWSも勉強したいのでAWSでデプロイなんかしてみたい