ゲーム開発
Unity
UnrealEngine
C++
Blender
Houdini
ゲーム数学
ゲームAI
グラフィックス
サウンド
アニメーション
GBDK
制作日記
IT関連
ツール開発
フロントエンド関連
サーバサイド関連
WordPress関連
ソフトウェア設計
おすすめ技術書
音楽
DTM
楽器・機材
ピアノ
ラーメン日記
四コマ漫画
その他
おすすめアイテム
おもしろコラム
  • ゲーム開発
    • Unity
    • UnrealEngine
    • C++
    • Blender
    • Houdini
    • ゲーム数学
    • ゲームAI
    • グラフィックス
    • サウンド
    • アニメーション
    • GBDK
    • 制作日記
  • IT関連
    • ツール開発
    • フロントエンド関連
    • サーバサイド関連
    • WordPress関連
    • ソフトウェア設計
    • おすすめ技術書
  • 音楽
    • DTM
    • 楽器・機材
    • ピアノ
  • ラーメン日記
    • 四コマ漫画
      • その他
        • おすすめアイテム
        • おもしろコラム
      1. ホーム
      2. 20221110_01

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

      Ruby on Railsサーバサイド関連
      2022-11-10

      マイケル
      マイケル
      みなさんこんにちは!
      マイケルです!
      エレキベア
      エレキベア
      こんにちクマ〜〜〜
      マイケル
      マイケル
      今日は前回から引き続き、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
      ↑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機能を作成していきます。

      ↑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です!
      ↑ページが表示された
      エレキベア
      エレキベア
      一覧表示はこれで完了クマ〜〜〜

      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 にアクセスすると
      登録ページが表示され、データ作成も正常に行えることが確認できます。
      ↑データ作成機能の完成!
      エレキベア
      エレキベア
      これでだいぶアプリっぽくなったクマ〜〜

      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機能は一通り完成です!
      ボタンを追加した一覧ページと編集ページは下記のようになります。
      ↑データ一覧ページ
      ↑編集ページ
      エレキベア
      エレキベア
      これだけでCRUD機能が作れるなんてめっちゃ楽クマ〜〜
      マイケル
      マイケル
      実際に触ってみると下記のような感じになります!
      エレキベア
      エレキベア
      感慨深いクマ〜〜〜

      リファクタリング

      マイケル
      マイケル
      ここから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データと紐づけてみようと思います。

      ↑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 %>
      
      ↑ユーザー一覧ページ
      <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 %>
      
      ↑ユーザーページ
      <h1>User</h1>
      <div>
        <p>
          <strong>Name:</strong>
          <%= @user.name %>
        </p>
      </div>
      <%= link_to "Back to users", users_path %>
      
      ↑ユーザ作成ページ
      エレキベア
      エレキベア
      ここまではTaskのCRUD作成とほぼ同じクマね

      Taskデータと紐づける

      マイケル
      マイケル
      Userデータが作成できたところで、Taskデータと紐づけていきます。
      マイケル
      マイケル
      まずは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 %>
      
      ↑ユーザーに紐づくタスクを表示した状態
      エレキベア
      エレキベア
      これだけで紐づくデータを表示できるのは便利クマね
      マイケル
      マイケル
      ついでに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
      ↑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
      ↑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 %>
      
      マイケル
      マイケル
      空文字や不正な文字を入力して作成しようとした際に
      このようにエラーメッセージが表示されれば完了です!
      エレキベア
      エレキベア
      なんて簡単な入力チェッククマ〜〜〜〜

      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にエラーメッセージを詰め込む
      マイケル
      マイケル
      タスク作成、タスク更新時に下記のようにエラーメッセージが表示されれば成功です!!
      マイケル
      マイケル
      ちなみに belongs_to を指定していた場合は、デフォルトで存在チェックが行われる設定となっているため、
      指定したユーザーIDが存在しない場合、「User must exist」と表示されるようになっています。
      エレキベア
      エレキベア
      存在チェックまでやってくれるクマか〜〜〜

      おわりに

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

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


      Ruby on Railsサーバサイド関連
      2022-11-10

      関連記事
      【Unity】GoでのランキングAPI実装とVPSへのデプロイ方法についてまとめる【Go言語】
      2024-04-14
      【Go言語】Gin、GORMでシンプルなREST APIを作成する【CRUD】
      2024-03-26
      【Rails7】Ruby on Rails7のローカル環境構築とScaffoldでのアプリ作成
      2022-11-06
      【ブログ改造計画】公開中のブログをGit管理して開発環境を構築する【WordPress】
      2022-04-27
      【ブログ改造計画】WordPressの基本機能とDocker環境の構築について【WordPress】
      2022-04-24
      【NAS】QNAPのNASで最低限しておくべきセキュリティ設定
      2022-02-21
      【Unity】UnityWebRequestを使ってCRUD機能を実装する【Ruby on Rails】
      2021-12-12
      【Docker】Dockerの基本的な使い方についてまとめる
      2021-05-02