はじめに
Railsを用いたスケジュール管理アプリを作成していきます。
※Rails学習の忘備録のため誤っている箇所があるかもしれません。ご了承ください。
環境
MacOS Sonoma 14.0
Ruby 3.0.4p208
Rails 6.1.3.2
要件
1 以下のページが表示される
(1)予定一覧ページ
・予定合計及び本日の日付が表示される
・詳細、編集、削除のリンク
・削除リンククリック時に確認メッセージ
(2)予定の新規追加ページ(バリデーション機能の実装)
・タイトルは20文字以内
・終了日は開始日より後の日付とする
・メモは500文字以内
(3)予定詳細ページ
(4)予定編集ページ(バリデーション機能の実装)
2 日付は日本時間とする
3 スケジュールの作成、編集に成功/失敗した場合はフラッシュメッセージを表示する
4 Railsのバージョンは6.1.3.2とする。
作成例
予定一覧
新規追加
予定詳細
予定編集
予定削除
アプリケーション作成
Railsバージョンの指定
要件でRailsのバージョンが指定されているため、バージョンを指定を行う。
$ rails _6.1.3.2_ new schedule --skip-bundle
Gemfileを編集
~/schedule内のGemfileを編集
gem 'rails', '~> 6.1.3', '>= 6.1.3.2'
gem 'rails', '= 6.1.3.2'
bundle installを実施
~/scheduleで以下のコマンドを実施
$ bundle install
Webpackerインストール
Rails6以降ではWebpackerインストールが必須になったため、インストール
$ rails webpacker:install
Rubyバージョンの確認
rails -vを実施して指定したバージョンになっているか確認。
$ rails -v
Rails 6.1.3.2と表示されれば成功。
rails s
でサーバーが無事起動するか確認。
$ rails s
http://localhost:3000/ にアクセスし、Rubyのバージョンを確認。
CRUD処理と7つのアクションとは
CRUDはそれぞれ以下を示す。
CRUD | 意味 | アクション | 用途 | httpメソッド |
---|---|---|---|---|
Create | 作成 | create | DBの登録処理 | post |
Read | 読み取り | new | 新規作成ページの表示 | get |
Read | 読み取り | index | 一覧を表示 | get |
Read | 読み取り | show | 詳細を表示 | get |
Read | 読み取り | edit | 編集ページを表示 | get |
Update | 更新 | update | DBの更新処理 | patch |
Delete | 削除 | destroy | DBの削除処理 | delete |
各ページの役割
ページ | 役割 | アクション |
---|---|---|
トップページ | スケジュールの全体表示 | index |
新規作成 | スケジュール作成ページの表示、作成 | new,create |
詳細 | スケジュールの個別表示 | show |
編集 | スケジュールの編集ページ表示、更新 | edit,update |
削除 | スケジュールの削除 | destroy |
Controller作成
rails generate controller <コントローラー名> <アクション名>
でコントローラを作成する。
コントローラー名は複数形、頭文字は大文字
$ rails generate controller Tasks index
tasks_controller.rbを編集(CRUD処理の実装)
~/schedule/app/controllers/tasks_controller.rbを編集する。
class TasksController < ApplicationController
def index
@tasks = Task.all
end
def new
@task = Task.new
end
def create
@task = Task.new(task_params)
if @task.save
flash[:notice_create] = "スケジュールを登録しました"
redirect_to :tasks
else
flash[:notice_no_create] = "スケジュールの登録に失敗しました"
render "new"
end
end
def show
@task = Task.find(params[:id])
end
def edit
@task = Task.find(params[:id])
end
def update
@task = Task.find(params[:id])
if @task.update(task_params)
flash[:notice_update] = "スケジュールを更新しました"
redirect_to :tasks
else
flash[:notice_no_update] = "スケジュールを更新できませんでした"
render "edit"
end
end
def destroy
@task = Task.find(params[:id])
@task.destroy
flash[:notice_destroy] = "スケジュールを削除しました"
redirect_to :tasks
end
private
def task_params # プライベートメソッド
params.require(:task).permit(:title, :start_date, :end_date, :is_all_day, :memo)
end
end
ルートファイルを編集
~/schedule/config/routes.rbを編集する。
Rails.application.routes.draw do
# resources :tasksと重複するため、以下の2行をコメントアウト
# get 'tasks/index'
# get 'tasks/new'
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
# 以下を追記
resources :tasks # ルーティングをまとめて設定
root to: 'tasks#index' # トップページの設定
end
routes(ラウツと発音するらしい)の確認
$ rails routes
以下のように表示されていれば問題なし。
Prefix | Verb | URI Pattern | Controller#Action |
---|---|---|---|
tasks_index | GET | /tasks/index(.:format) | tasks#index |
tasks_new | GET | /tasks/new(.:format) | tasks#new |
tasks | GET | /tasks(.:format) | tasks#index |
POST | /tasks(.:format) | tasks#create | |
new_task | GET | /tasks/new(.:format) | tasks#new |
edit_task | GET | /tasks/:id/edit(.:format) | tasks#edit |
task | GET | /tasks/:id(.:format) | tasks#show |
PATCH | /tasks/:id(.:format) | tasks#update | |
PUT | /tasks/:id(.:format) | tasks#update | |
DELETE | /tasks/:id(.:format) | tasks#destroy |
モデル作成
$ rails g model Task title:string start_date:date end_date:date is_all_day:boolean memo:string
~/schedule/app/dbに以下のファイルが作成される。
class CreateTasks < ActiveRecord::Migration[6.1]
def change
create_table :tasks do |t|
t.string :title
t.date :start_date
t.date :end_date
t.boolean :is_all_day
t.string :memo
t.timestamps
end
end
end
マイグレーションファイルからテーブルを作成する。
rails db:migrate
-- create_table(:tasks)
-> 0.0018s
が表示されれば成功
rails dbconsoleを実施し、tableが作成されているか確認
$ rails dbconsole
$ .tables
tasksが表示されていることを確認。
$ .schema tasks
以下のように表示されれば問題なし。
CREATE TABLE IF NOT EXISTS "tasks" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "title" varchar, "start_date" date, "end_date" date, "is_all_day" boolean, "memo" varchar, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL);
レイアウトの作成
ヘッダーの作成(パーシャル)
~/schedule/app/views/にsharedフォルダを作成し、_partial.html.erbファイルを新規作成
<div class="partial">
<h4>スケジュール管理アプリ</h4>
</div>
スタイルシートの作成
~/schedule/app/assets/stylesheets/内にcommon.scssを作成
header {
width: 100%;
padding: 15px;
margin-bottom: 30px;
border-bottom: 7px solid orange;
}
footer{
width: 100%;
padding: 15px;
margin-top: 30px;
border-top: 7px solid orange;
}
.partial {
color: white;
background-color: black;
text-align: center;
padding: 1px;
}
table th {
padding: 10px 20px;
border-bottom: 2px solid gray;
}
table td {
background-color: #f9ecd5;
padding: 10px 20px;
}
.notice {
background-color: #ccf;
padding: 5px;
}
予定一覧ページ
~/schedule/app/views/tasks/index.html.erb
<h3>予定一覧</h3>
<table>
<thead>
<tr>
<th>id</th>
<th>タイトル</th>
<th>開始日</th>
<th>終了日</th>
<th>終日</th>
<th>更新日時</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<% @tasks.each do |task| %>
<tr>
<td><%= task.id %></td>
<td><%= task.title %></td>
<td><%= task.start_datetime %></td>
<td><%= task.end_datetime %></td>
<td><%= task.is_all_day %></td>
<td><%= task.updated_at %></td>
<td></td>
<td></td>
<td></td>
</tr>
<% end %>
</tbody>
</table>
<p><%= link_to "予定の新規登録", :new_task %></p>
予定の新規登録ページ
~/schedule/app/views/tasks/new.html.erb
<h3>ユーザー新規作成</h3>
<%= form_with model: @task do |f| %>
<table>
<tr>
<th><%= f.label :title ,"タイトル" %></th>
<td><%= f.text_field :title %></td>
</tr>
<tr>
<th><%= f.label :start_datetime ,"開始日" %></th>
<td><%= f.datetime_field :start_datetime %></td>
</tr>
<tr>
<th><%= f.label :end_datetime ,"終了日" %></th>
<td><%= f.datetime_field :end_datetime %></td>
</tr>
<tr>
<th><%= f.label :is_all_day ,"終日の場合はチェックを入れます" %></th>
<td><%= f.check_box :is_all_day %></td>
</tr>
<tr>
<th><%= f.label :memo ,"スケジュールメモ" %></th>
<td><%= f.text_area :memo %></td>
</tr>
</table>
<div>
<ul>
<li><%= f.submit "登録完了する"%></li>
<li><%= link_to "予定一覧に戻る", :tasks %></li>
</ul>
</div>
<% end %>
予定の編集ページ
~/schedule/app/views/tasks/edit.html.erb
<%= render "shared/partial" %>
<h3>予定の編集</h3>
<%= form_with model: @task do |f| %>
<table>
<tr>
<th><%= f.label :title ,"タイトル" %></th>
<td><%= f.text_field :title %></td>
</tr>
<tr>
<th><%= f.label :start_date ,"開始日" %></th>
<td><%= f.date_field :start_date %></td>
</tr>
<tr>
<th><%= f.label :end_date ,"終了日" %></th>
<td><%= f.date_field :end_date %></td>
</tr>
<tr>
<th><%= f.label :is_all_day ,"終日の場合はチェックを入れます" %></th>
<td><%= f.check_box :is_all_day %></td>
</tr>
<tr>
<th><%= f.label :memo ,"スケジュールメモ" %></th>
<td><%= f.text_area :memo %></td>
</tr>
</table>
<div>
<ul>
<li><%= f.submit "編集を完了する"%></li>
<li><%= link_to "キャンセル", :tasks %></li>
</ul>
</div>
<% if flash[:notice_no_update] %>
<p class="notice"><%= flash[:notice_no_update] %></p>
<% end %>
<%= render "shared/error", obj: @task %>
<% end %>
予定の詳細ページ
~/schedule/app/views/tasks/show.html.erb
<%= render "shared/partial" %>
<%= link_to "一覧に戻る", :tasks %>
<%= @task.title %>
<%= form_with model: @task do |f| %>
<table>
<tr>
<th>開始日</th>
<td><%= l @task.start_date %></td>
</tr>
<tr>
<th>終了日</th>
<td><%= l @task.end_date %></td>
</tr>
<tr>
<th>終日</th>
<td><%= @task.is_all_day ? '◯': '' %></td>
</tr>
<tr>
<th>スケジュールメモ</th>
<td><%= @task.memo %></td>
</tr>
</table>
<% end %>
確認
$ rails s
を実行し、ブラウザでhttp://lovalhost:30000
にアクセスし、予定一覧の画面が表示されれば成功。
まとめ
環境構築が一番の難関だったりします。
問題解決能力がエンジニアに必要とされるスキルの一つと学びました。
参考リンク