【Rails7】Ruby on Rails7で主要な機能をtodoアプリで学ぶ

Ruby on Rails
マイケル
マイケル
みなさんこんにちは!
マイケルです!
エレキベア
エレキベア
こんにちクマ〜〜〜
マイケル
マイケル
今日は前回から引き続き、Railsを触っていきます!
エレキベア
エレキベア
前回は確かScaffoldで簡単なアプリを作って触ったクマね
マイケル
マイケル
Railsの概要やイメージについては、前回の記事をご参照ください!
今回はScaffoldは使用せずに、下記のような手順で 一からtodoアプリを開発 していこうかと思います。

  • TaskデータのCRUD機能作成
  • UserデータとTaskデータの関連付け
  • バリデーションの追加

エレキベア
エレキベア
基本的なアプリの作り方が分かりそうクマね
楽しみクマ〜〜〜〜
マイケル
マイケル
それでは早速触っていこう!!
スポンサーリンク

事前準備

アプリの雛形を作成

マイケル
マイケル
まずは前回と同様の手順で、アプリを新規作成しましょう!
コマンドは下記のようになります。
# フォルダ作成
mkdir todo_app_standard
cd todo_app_standard

# Gemfile作成
bundle init

# railsを追記してbundle install
echo "gem 'rails', '~>7.0.1'" >> Gemfile
bundle install --path vendor/bundle
bundle exec rails -v

# railsアプリを新規作成(余計なものは省く)
# 何か聞かれたら全てYES
bundle exec rails new . --skip-action-mailer --skip-action-mailbox --skip-action-text --skip-action-cable

# サーバ起動
# http://127.0.0.1:3000
bundle exec rails server
ScreenShot 2022 11 06 12 52 21↑http://127.0.0.1:3000 で起動した画面
マイケル
マイケル
無事Rails画面が表示されれば完了です!
エレキベア
エレキベア
手慣れたもんクマ〜〜〜

よく使用するrailsコマンド

マイケル
マイケル
これからアプリを作っていくにあたり様々なrailsコマンドが出てきますが、
よく使用するコマンド一覧は下記のようになります!
途中でこれなんだっけ?と思ったら、こちらやRailsドキュメントを見てみましょう。
# サーバー起動
rails server
# routes一覧の確認
rails routes
# Railsコンソールに入る
rails console

###############
# MVCデータ作成
###############
# generate は g に省略可能
# modelとcontrollerで単数系、複数形の指定が異なるため注意

# model作成
rails generate model [モデル名(単数形)] [項目名:型]
# controller(+view)作成
rails generate controller [モデル名(複数形)] [関数名]
# resource(model+controller+routes)作成
rails generate resource [モデル名(単数形)] [項目名:型]
# scaffold(テンプレート)作成
rails generate scaffold [モデル名(単数形)] [項目名:型]

# 誤ってgenerateした場合は下記のようにdestroy(or d)で実行前に戻すことができる
rails destroy controller [モデル名(複数形)] [関数名]

###############
# DB関連
###############
# DB作成
# デフォルトのSQLite以外を使用する場合、初回のみ
rails db:create
# テーブル作成
rails db:migrate
# データ破棄
rails db:reset
# テーブルを初期状態に戻す
rails db:migrate VERSION=0
# seedデータ設定
rails db:seed

railsコマンド – Railsドキュメント

エレキベア
エレキベア
最初は分からなくなりがちクマが、
慣れれば簡単クマ〜〜〜

TaskデータのCRUD機能を作る

マイケル
マイケル
それでは早速アプリを作っていきましょう!
まずは下記のようなTaskデータのCRUD機能を作成していきます。
UntitledImage
↑Taskデータ
エレキベア
エレキベア
これは楽勝クマ〜〜〜

model、controllerの作成

マイケル
マイケル
まずはmodelとcontrollerを作成していくのですが、大きく
・resourceとして作成する方法
・model、controllerそれぞれ作成する方法

の2つの方法があります。
どちらも試してみましょう!
マイケル
マイケル
まずはresourceで作成する方法から!
下記コマンドで作成することができます。
# resourceコマンドで作成
bundle exec rails generate resource Task content:string
マイケル
マイケル
すると、modelやcontroller等のファイルがまとめて作成されるのが確認できます。
config/routes.rb にもresourcesとしてルーティングが設定されており、一通りのパスが使用できる状態になっています。
Rails.application.routes.draw do
  resources :tasks
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
  # Defines the root path route ("/")
  # root "articles#index"
end
↑resourcesとしてルーティングが設定されている
                            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 routesで確認すると、一通りのパスが設定されていることを確認できる
マイケル
マイケル
resourceでの作成が確認できたところで、一旦元の状態に戻しましょう!
generateコマンドで作成したものは、同様にdestroyコマンドを使用することで作成されたファイルを削除することができます。
# 一旦戻す
bundle exec rails destroy resource Task content:string
エレキベア
エレキベア
これなら間違ってコマンド実行した時も安心クマね
マイケル
マイケル
初期状態に戻ったところで、次はmodel、controllerをそれぞれ作成してみましょう!
コマンドは下記を使用しますが、controller作成時にはmodel名を複数形で指定する必要がある点には注意しましょう!
# model作成
bundle exec rails generate model Task content:string

# controller作成
bundle exec rails generate controller Tasks
エレキベア
エレキベア
Railsはその辺の規約が厳しかったクマね
マイケル
マイケル
これで基本的にはresourceでの作成とほぼ同じ状態になったのですが、
routes.rbには何も記述されていない状態になっています。
こちらは下記のように修正してresourcesとしてルーティングを指定しておきましょう!
Rails.application.routes.draw do
  resources :tasks
end
エレキベア
エレキベア
これでさっきと同じ状態になったクマね
マイケル
マイケル
最後に、model作成時にdb/migrate/配下にテーブル定義が記述されたマイグレーションファイルも作成されたかと思います。
こちらはdb:migrateを実行してテーブルを作成しておきましょう!
# テーブル作成
bundle exec rails db:migrate
エレキベア
エレキベア
これで準備完了クマ〜〜〜

Taskデータの一覧表示

マイケル
マイケル
準備が出来たところで、一番簡単なTaskの一覧表示機能を作成してみましょう!
一覧表示のアクションはtasks#indexで指定されていたので、下記のようにcontrollerクラスにindex関数を追加しましょう!
class TasksController < ApplicationController
  # Task一覧画面表示
  def index
    @tasks = Task.all
  end
end
↑index関数の追加
マイケル
マイケル
controllerクラスで設定したインスタンス変数は、ビュークラスからも参照することができます。
views/tasks/index.html.erb ファイルを作成して、下記のように表示処理を記述してみましょう!
<h1>Tasks</h1>
<div>
  <% @tasks.each do |task| %>
    <p>Content: <%= task.content %></p>
  <% end %>
</div>
↑tasksをループで回して表示する
マイケル
マイケル
この状態で http://127.0.0.1:3000/tasks にアクセスすると、下記のようにページが表示されると思います。
まだデータが無いため、現段階ではタイトルが表示されていればOKです!
ScreenShot 2022 11 06 22 54 06↑ページが表示された
エレキベア
エレキベア
一覧表示はこれで完了クマ〜〜〜

Taskデータの作成

マイケル
マイケル
次はデータが作成できるようにしていきます!
new、create関数を追加して、下記のように処理を記述しましょう!
class TasksController < ApplicationController
  # Task一覧画面表示
  def index
    @tasks = Task.all
  end
  # Task作成画面表示
  def new
    @task = Task.new
  end
  # Task作成処理
  def create
    @task = Task.new(task_params)
    if @task.save
      redirect_to tasks_path
    end
  end
  private
  # ストロングパラメータ
  # permitで指定した項目を許可する
  def task_params
    params.require(:task).permit(:content)
  end
end
↑new、create関数の追加
マイケル
マイケル
task_paramsの部分はストロング・パラメータと呼ばれる仕組みで、
permitにより渡す値を許可して制限することができます。
エレキベア
エレキベア
想定外の項目が渡されないようにできるクマね
マイケル
マイケル
登録ページとしてviews/tasks/new.html.erb を作成し、下記のように記述しましょう!
form_with を使用することでmodelとformを紐づけています。
form.submit でsubmitしたものはHTMLと同様POSTメソッドで送信されるため、入力データはcreateアクションに渡される流れになります。
<h1>New Task</h1>
<%= form_with(model: @task) do |form| %>
  <div><%= form.label :content %></div>
  <div><%= form.text_area :content %></div>
  <div><%= form.submit %></div>
<% end %>
<%= link_to "Back to tasks", tasks_path %>
↑登録ページの作成
マイケル
マイケル
views/tasks/index.html.erb にも登録ページのリンクを追加しておきましょう!
これでデータ作成機能の完成です!
<h1>Tasks</h1>
<div>
  <% @tasks.each do |task| %>
    <p>Content: <%= task.content %></p>
  <% end %>
</div>
<%= link_to "New task", new_task_path %>
↑登録ページへのリンクを追加
マイケル
マイケル
この状態でリンクを踏むか http://127.0.0.1:3000/tasks/new にアクセスすると
登録ページが表示され、データ作成も正常に行えることが確認できます。
ScreenShot 2022 11 06 23 17 56↑データ作成機能の完成!
エレキベア
エレキベア
これでだいぶアプリっぽくなったクマ〜〜

Taskデータの更新・削除

マイケル
マイケル
最後に、データの更新・削除も行えるようにしてみましょう!
下記のようにedit、update、destroy関数を追加します。
class TasksController < ApplicationController
・・・略・・・
  # Task編集画面表示
  def edit
  end
  # Task更新処理
  def update
    @task = Task.find(params[:id])
    if @task.update(task_params)
      redirect_to tasks_path
    end
  end
  # Task削除処理
  def destroy
    @task = Task.find(params[:id])
    @task.destroy
    redirect_to tasks_path
  end
・・・略・・・
end
↑edit、update、destroy関数の追加
マイケル
マイケル
そして編集ページを views/tasks/edit.html.erb として作成し、
下記のように記述します!
<h1>Editing task</h1>
<%= form_with(model: @task) do |form| %>
  <div><%= form.label :content %></div>
  <div><%= form.text_area :content %></div>
  <div><%= form.submit %></div>
<% end %>
<%= link_to "Back to tasks", tasks_path %>
↑編集ページの作成
マイケル
マイケル
編集ページへのリンクと削除処理はデータ一覧ページにボタンとして追加します!
整理して、views/tasks/index.html.erb は下記のようになります。
<h1>Tasks</h1>
<div>
  <% @tasks.each do |task| %>
    <div style="display: flex;">
        <div style="width: 200px;">Content: <%= task.content %></div>
        <div><%= button_to "edit", edit_task_path(task), method: :get %></div>
        <div><%= button_to "delete", task_path(task), method: :delete %></div>
    </div>
  <% end %>
</div>
<%= link_to "New task", new_task_path %>
↑リンクと削除ボタンの追加
マイケル
マイケル
なお、Rails7ではlink_toでdeleteメソッドが簡単に送れないようになっているようなので、
ボタンで対処する形としています。
エレキベア
エレキベア
そんな罠が・・・
マイケル
マイケル
以上でCRUD機能は一通り完成です!
ボタンを追加した一覧ページと編集ページは下記のようになります。
ScreenShot 2022 11 06 23 58 23↑データ一覧ページ
ScreenShot 2022 11 06 23 58 33↑編集ページ
エレキベア
エレキベア
これだけでCRUD機能が作れるなんてめっちゃ楽クマ〜〜
マイケル
マイケル
実際に触ってみると下記のような感じになります!
01 todo
エレキベア
エレキベア
感慨深いクマ〜〜〜

リファクタリング

マイケル
マイケル
ここからUserデータを作成していく・・・前に、
軽くリファクタリングしておきましょう!
パーシャル機能で共通部分を抜き出す
マイケル
マイケル
まずはパーシャル機能を用いて、viewの重複部分を共通化してみます。
ファイル名の頭に「_」を付けることで、「render “XXX”」の形で使用できるようになります!
<%= form_with(model: task) do |form| %>
  <div><%= form.label :content %></div>
  <div><%= form.text_area :content %></div>
  <div><%= form.submit %></div>
<% end %>
↑formをパーシャルとして切り出す
<h1>New Task</h1>
<%= render "form", task: @task %>
<%= link_to "Back to tasks", tasks_path %>
↑登録ページのform部分を差し替える
<h1>Editing task</h1>
<%= render "form", task: @task %>
<%= link_to "Back to tasks", tasks_path %>
↑編集ページのform部分を差し替える
エレキベア
エレキベア
共通部品として抜き出せるのは便利クマ〜〜
before_actionで事前処理を抜き出す
マイケル
マイケル
controllerクラスの処理もよく見ると、同じようなデータ設定処理が重複していることが分かります。
before_action として切り出すことで、指定した関数の頭で呼び出すよう共通化してみましょう!
class TasksController < ApplicationController
  before_action :set_task, only: %i[edit update destroy]
・・・略・・・
  # Task編集画面表示
  def edit
  end
  # Task更新処理
  def update
    if @task.update(task_params)
      redirect_to tasks_path
    end
  end
  # Task削除処理
  def destroy
    @task.destroy
    redirect_to tasks_path
  end
  private
・・・略・・・
  # id指定でtaskを検索して設定
  def set_task
    @task = Task.find(params[:id])
  end
end
↑事前処理をbefore_actionとして共通化
エレキベア
エレキベア
これもよく使いそうな機能クマね〜〜

Userデータを作成して紐づける

マイケル
マイケル
次はUserデータを作成して、最終的には下記のようにTaskデータと紐づけてみようと思います。
UntitledImage
↑UserとTaskを1:Nで紐づける
エレキベア
エレキベア
関連性を定義するクマね

Userデータと関連ページの作成

マイケル
マイケル
まずはUserデータと関連ページをTaskデータと同様に作成します。
今回はresources指定ではなく、
・ユーザー一覧ページ
・ユーザーページ
・ユーザー作成ページ

の3つを作るために最低限必要な関数を指定して作成してみます。
# userモデル、データ作成
bundle exec rails generate model User name:string
bundle exec rails db:migrate

# 関数名を指定してcontroller作成
bundle exec rails generate controller Users index show new create
マイケル
マイケル
controller作成時に関数名を指定した場合は、
下記のように関数名に対応したviewも一緒に作成されることが確認できます。
app/views/users
├── create.html.erb
├── index.html.erb
├── new.html.erb
└── show.html.erb
エレキベア
エレキベア
一緒に作ってくれるのは便利クマね
マイケル
マイケル
この内、createページは今回不要なため削除します。
# createページは不要なため削除
rm app/views/users/create.html.erb
マイケル
マイケル
そして各関数の処理とroutesの指定を下記のように記述します。
class UsersController < ApplicationController
  # user一覧画面表示
  def index
    @users = User.all
  end
  # user画面表示
  def show
    @user = User.find(params[:id])
  end
  # user作成画面表示
  def new
    @user = User.new
  end
  # user作成処理
  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to users_path
    end
  end
  private
  def user_params
    params.require(:user).permit(:name)
  end
end
↑各関数の処理
Rails.application.routes.draw do
  resources :tasks
  get 'users', to: "users#index", as: "users"
  get 'users/new', to: "users#new", as: "new_user"
  get 'users/:id', to: "users#show", as: "user"
  post 'users', to: "users#create"
end
↑routesの指定
エレキベア
エレキベア
今回はresourcesじゃなく一つ一つ指定しているクマね
マイケル
マイケル
あとは各関数に対応するページをそれぞれ作成すれば完了です!
<h1>Users</h1>
<div>
  <% @users.each do |user| %>
    <div style="display: flex;">
      <div style="width: 160px;">User: <%= user.name %></div>
      <div><%= button_to "show", user_path(user), method: :get %></div>
    </div>
  <% end %>
</div>
<%= link_to "New task", new_user_path %>
↑ユーザー一覧ページ
ScreenShot 2022 11 08 0 12 06
<h1>New User</h1>
<%= form_with(model: @user) do |form| %>
  <div><%= form.label :name %></div>
  <div><%= form.text_area :name %></div>
  <div><%= form.submit %></div>
<% end %>
<%= link_to "Back to users", users_path %>
↑ユーザーページ
ScreenShot 2022 11 08 0 12 29
<h1>User</h1>
<div>
  <p>
    <strong>Name:</strong>
    <%= @user.name %>
  </p>
</div>
<%= link_to "Back to users", users_path %>
↑ユーザ作成ページ
ScreenShot 2022 11 08 0 12 55
エレキベア
エレキベア
ここまではTaskのCRUD作成とほぼ同じクマね

Taskデータと紐づける

マイケル
マイケル
Userデータが作成できたところで、Taskデータと紐づけていきます。
UntitledImage
マイケル
マイケル
まずはTaskデータにuser_idを追加しましょう!
下記のコマンドで追加のマイグレーションファイルを作成し、データを再作成します。
# taskデータにuser_idを追加
bundle exec rails generate migration AddUserIdToTask user_id:integer

# テーブル再作成
bundle exec rails db:reset
bundle exec rails db:migrate
エレキベア
エレキベア
途中で項目追加もできるクマね
マイケル
マイケル
そしてuserモデルとtaskモデルを紐付けます。
下記のようにそれぞれhas_many、belongs_toを指定することで、1:Nの関係にすることができます。
class User < ApplicationRecord
  has_many :tasks
end
class Task < ApplicationRecord
  belongs_to :user
end
マイケル
マイケル
関連付けは他にも種類があります。
詳細は下記をご参照ください。

Active Record の関連付け

エレキベア
エレキベア
いろんなのが用意されてるクマね〜〜
マイケル
マイケル
次は関連付けの挙動を確認するために、デフォルトのデータを設定しておきます。
下記のようにしてuserとそれに紐づくtaskのデータをseedsに定義、実行します。
# user作成
user = User.create!(
  name: "test"
)
# userに紐づいたtaskを作成
3.times do |n|
  user.tasks.create!(
    content: "task#{n}"
  )
end
# シードデータの作成
bundle exec rails db:seed
マイケル
マイケル
rails console で作成されたデータを見てみましょう。
Userにtaskが紐づいている状態のため、user.tasksといった形でアクセスすることができます。
irb(main):001:0> user = User.first
  User Load (0.1ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<User:0x0000000106a72ba8 id: 1, name: "test", created_at: Tue, 08 Nov 2022 14:14:51.570018000 UTC +00:00, updated_at: Tue, 08 Nov 2022 14:14:51.570018000 UTC +00:00>

# userに紐づいたtaskを参照できる
irb(main):002:0> user.tasks.all
  Task Load (0.1ms)  SELECT "tasks".* FROM "tasks" WHERE "tasks"."user_id" = ?  [["user_id", 1]]
=>                                                                                   
[#<Task:0x00000001077b3268 id: 1, content: "task0", created_at: Tue, 08 Nov 2022 14:14:51.595879000 UTC +00:00, updated_at: Tue, 08 Nov 2022 14:14:51.595879000 UTC +00:00, user_id: 1>,
 #<Task:0x000000010777b0c0 id: 2, content: "task1", created_at: Tue, 08 Nov 2022 14:14:51.599320000 UTC +00:00, updated_at: Tue, 08 Nov 2022 14:14:51.599320000 UTC +00:00, user_id: 1>,
 #<Task:0x000000010777af08 id: 3, content: "task2", created_at: Tue, 08 Nov 2022 14:14:51.601999000 UTC +00:00, updated_at: Tue, 08 Nov 2022 14:14:51.601999000 UTC +00:00, user_id: 1>]
irb(main):003:0> user.tasks.first
  Task Load (0.1ms)  SELECT "tasks".* FROM "tasks" WHERE "tasks"."user_id" = ? ORDER BY "tasks"."id" ASC LIMIT ?  [["user_id", 1], ["LIMIT", 1]]
=> #<Task:0x0000000107a90198 id: 1, content: "task0", created_at: Tue, 08 Nov 2022 14:14:51.595879000 UTC +00:00, updated_at: Tue, 08 Nov 2022 14:14:51.595879000 UTC +00:00, user_id: 1>

# taskからの参照もできる
irb(main):004:0> task = user.tasks.first
  Task Load (0.1ms)  SELECT "tasks".* FROM "tasks" WHERE "tasks"."user_id" = ? ORDER BY "tasks"."id" ASC LIMIT ?  [["user_id", 1], ["LIMIT", 1]]
=> #<Task:0x0000000107ce3d50 id: 1, content: "task0", created_at: Tue, 08 Nov 2022 14:14:51.595879000 UTC +00:00, updated_at: Tue, 08 Nov 2022 14:14:51.595879000 UTC +00:00, user_id: 1>
irb(main):005:0> task.user
=> #<User:0x0000000106a72ba8 id: 1, name: "test", created_at: Tue, 08 Nov 2022 14:14:51.570018000 UTC +00:00, updated_at: Tue, 08 Nov 2022 14:14:51.570018000 UTC +00:00>
エレキベア
エレキベア
これが関連付けの威力クマか・・・
マイケル
マイケル
準備が出来たところで実際に表示してみましょう!
ユーザページで user.tasks をループで表示してみます。
<h1>User</h1>
<div>
  <p>
    <strong>Name:</strong>
    <%= @user.name %>
  </p>
</div>
<div>
  <strong>Tasks:</strong>
  <% @user.tasks.each do |task| %>
    <div style="display: flex;">
      <div style="width: 160px;"><%= task.content %></div>
      <div><%= button_to "edit", edit_task_path(task), method: :get %></div>
    </div>
  <% end %>
</div>
<%= link_to "Back to users", users_path %>
ScreenShot 2022 11 08 23 57 13↑ユーザーに紐づくタスクを表示した状態
エレキベア
エレキベア
これだけで紐づくデータを表示できるのは便利クマね
マイケル
マイケル
ついでにeditボタンも追加してページを行き来できるようにしてみます。
合わせてタスク更新後もページに留まり続けるようにしました。
<h1>Editing task</h1>

<%= render "form", task: @task %>
<div><%= link_to "Back to tasks", tasks_path %></div>
<div><%= link_to "Back to user", user_path(@task.user) %></div>
  # Task更新処理
  def update
    @task.update(task_params)
  end
ScreenShot 2022 11 08 23 57 28↑userページと行き来できるようにする
マイケル
マイケル
最後にタスク作成画面にuser_idを追加すれば完了です!
<h1>New Task</h1>

<%= form_with(model: @task) do |form| %>
  <div><%= form.label :user_id %></div>
  <div><%= form.text_field :user_id %></div>
  <div><%= form.label :content %></div>
  <div><%= form.text_area :content %></div>
  <div><%= form.submit %></div>
<% end %>
<%= link_to "Back to tasks", tasks_path %>
  def task_params
    params.require(:task).permit(:user_id, :content)
  end
ScreenShot 2022 11 09 0 21 06↑UserIdの入力項目を追加
エレキベア
エレキベア
これでTaskとUserの関連付けは完了クマ〜〜〜

バリデーションを追加する

マイケル
マイケル
Todoアプリ作成は以上になりますが、最後にデータ作成時のバリデーションを追加してみます。

Userのバリデーション

マイケル
マイケル
バリデーションはActiveRecordの機能を使うと楽に実装できます。
下記はユーザー名に
・入力必須
・最大10文字
・アルファベット入力のみ

の3つのチェックを追加した記述となります。
class User < ApplicationRecord
  has_many :tasks
  validates :name, presence: true, length: { maximum: 10 }, format: { with: /\A[a-zA-Z]+\z/ }
end
↑ユーザー名にバリデーションを追加
エレキベア
エレキベア
これだけでチェックが行えるのクマね
マイケル
マイケル
他のバリデーションの種類については、下記をご参照ください!

Active Record バリデーション – Railsガイド

エレキベア
エレキベア
こんなに用意されてるクマか〜〜〜
マイケル
マイケル
エラーメッセージはerrors.full_messagesで取得することができます。
Railsのflash機能を用いて、作成失敗時には下記のように設定してみます。
  # user作成処理
  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to users_path
    else
      flash[:errors] = @user.errors.full_messages
      redirect_to action: :new
    end
  end
↑エラーメッセージをflashに詰め込む
マイケル
マイケル
flashはページ遷移時に一度切りで表示するために設定する機能になります。
下記のようにメッセージを表示するパーシャル部品を作成しましょう。
<% if flash[:errors] %>
  <ul style="color: red;">
    <% flash[:errors].each do |message| %>
      <li><%= message %></li>
    <% end %>
  </ul>
<% end %>
↑flashメッセージが設定された際に表示する
マイケル
マイケル
あとはユーザー作成ページにrenderを追加するだけです!
<h1>New User</h1>

<%= render 'shared/flash_error_messages' %>

<%= form_with(model: @user) do |form| %>
  <div><%= form.label :name %></div>
  <div><%= form.text_area :name %></div>
  <div><%= form.submit %></div>
<% end %>
<%= link_to "Back to users", users_path %>
ScreenShot 2022 11 10 1 36 23
マイケル
マイケル
空文字や不正な文字を入力して作成しようとした際に
このようにエラーメッセージが表示されれば完了です!
エレキベア
エレキベア
なんて簡単な入力チェッククマ〜〜〜〜

Taskのバリデーション

マイケル
マイケル
Taskの方もバリデーションを追加してみます。
Userと同じように
・入力必須
・最大20文字
というように設定してみました。
class Task < ApplicationRecord
  belongs_to :user
  validates :content, presence: true, length: { maximum: 20 }
end
マイケル
マイケル
タスク作成ページ、タスク更新ページも同じようにshared/flash_error_messagesを追加しましょう。
<h1>New Task</h1>
<%= render 'shared/flash_error_messages' %>
<%= form_with(model: @task) do |form| %>
  <div><%= form.label :user_id %></div>
  <div><%= form.text_field :user_id %></div>
  <div><%= form.label :content %></div>
  <div><%= form.text_area :content %></div>
  <div><%= form.submit %></div>
<% end %>
<%= link_to "Back to tasks", tasks_path %>
↑タスク作成ページ
<h1>Editing task</h1>
<%= render 'shared/flash_error_messages' %>
<%= render "form", task: @task %>
<div><%= link_to "Back to tasks", tasks_path %></div>
<div><%= link_to "Back to user", user_path(@task.user) %></div>
↑タスク更新ページ
マイケル
マイケル
そしてcontrollerのcreate、updateも同様に
flashにエラーメッセージを詰め込めば完了です!!
  # Task作成処理
  def create
    @task = Task.new(task_params)
    if @task.save
      redirect_to tasks_path
    else
      flash[:errors] = @task.errors.full_messages
      redirect_to action: :new
    end
  end
・・・略・・・
  # Task更新処理
  def update
    if not @task.update(task_params)
      flash[:errors] = @task.errors.full_messages
    end
    redirect_to action: :edit
  end
↑flashにエラーメッセージを詰め込む
マイケル
マイケル
タスク作成、タスク更新時に下記のようにエラーメッセージが表示されれば成功です!!
ScreenShot 2022 11 10 1 42 17
マイケル
マイケル
ちなみに belongs_to を指定していた場合は、デフォルトで存在チェックが行われる設定となっているため、
指定したユーザーIDが存在しない場合、「User must exist」と表示されるようになっています。
エレキベア
エレキベア
存在チェックまでやってくれるクマか〜〜〜

おわりに

マイケル
マイケル
というわけで今回はRailsでTodoアプリを作ってみました!
どうだったかな??
エレキベア
エレキベア
いろんな機能が用意されていて便利だと思ったクマ〜〜〜
マイケル
マイケル
Railsという名の遠り、実装でなるべく迷わないように作られていて、
人気な理由が分かったね!
楽しいからこれからたまに触りながら慣れていこう!!
マイケル
マイケル
それでは今日はこの辺で!
アデューーー!!
エレキベア
エレキベア
クマ〜〜〜〜

【Rails7】Ruby on Rails7で主要な機能をtodoアプリで学ぶ 〜間〜



コメント