🔴

【Ruby】RailsのCRUDとは

2024/04/07に公開

はじめに:

プログラミング初学者がRailsアプリケーションを動かす際に必要な知識として、CRUD(Create,Read,Update,Delete)が挙げられる。プログラミング初学者がVScodeを用いてRails環境の構築後、CRUD処理を実装できることを目標とした記事となっている。

この記事を読むことで得られる結果:

ローカル環境(自分のPC)にインストールされているVScodeからRailsアプリケーションをブラウザで表示させ、CRUDを理解しながら処理ができる。

開発環境:

  • windows 11
  • Vscode 1.87.2
  • Ubuntu 22.04
  • wsl 2.1.5.0
  • ruby 3.2.3
  • rails 6.1.7
  • sqlite3 3.37.2
  • node 12.22.9
  • nmp 10.5.0

開発環境の構築がまだの方はこちらから:

https://zenn.dev/code_journey_ys/articles/c0cc5dd5372036

ここから使うフォルダは、この2つ。(★)のファイルを使用していく。

フォルダ名 目的・内容
app/ モデル(★)、ビュー(★)、コントローラ(★)のディレクトリ
config/ ルーティング(★)や言語設定やその他各種設定ファイルのディレクトリ
db/ データベースに関するディレクトリ(★)

CRUDとは(基礎):

CRUDの基本的なデータの流れ

データを保存し、表示したり更新する流れは、以下のようになる。


CRUDのイメージ図
MVCモデルの全体をイメージして頂き、コントローラにCRUDを記述しておくと様々な処理ができると想像できるでしょう。

CRUDは4つの処理名ということではない!?

CRUDは先ほど説明した。Create,Read,Upadate,Deleteという4つの処理だけだと思いがちですが、実は7つの処理のことを指していると覚えた方が良いです。

Webアプリケーションの大半はこのCRUD処理が必要になってきます。毎度コントローラにこの7つのアクションを記述し、それらに対するルーティングを設定するのは大変ですよね。

そこで登場するのがresourcesメソッドというものです。RESTfulな設計が可能となる。

RESTとは(発展編)

以下の原則に沿った Webサービスの設計モデルのことを指す。
1.セッションなどの状態管理を行わない
2.情報を操作する命令が体系化されて定義・共有される
3.情報に対して汎用的な構文で一意に識別される
4.情報に、別の情報や別の状態へのリンクを含めることができる

簡単に要約すると、なに(アクション)に対してどうするか(HTTPメソッド)でルート定義をわかりやすく設定しているモデルのこと。

RESTfullとは(発展編)

・RESTの性質を持つルート設計のこと
・基本的にRailsのルート設計はRESTfulな設計となっている。

CRUD処理を実装してみよう(応用):

まだMVCモデルの理解ができてない方はこちらを読んでからの方がよいです。
https://zenn.dev/code_journey_ys/articles/50ac29298d636f

1.resourcesメソッドを用いてルーティング設定しよう

1: ターミナルから現在作成されているルーティングを確認していく。

rails routes

2: 現在関係のないルーティングも表示されてしまうため、もう少し見やすい方法で確認をしていく。

rails routes -g posts

※[-g]というOptionを用いると絞り込みが可能。

3: ターミナルに表示されたルーティングを確認する。

    Prefix Verb URI Pattern           Controller#Action
    posts  GET  /posts(.:format)      posts#index

4: ルーティングファイル(routes.rb)を編集する。
この状態から

    Rails.application.routes.draw do
      get 'posts' #削除
    end

以下に変更

    Rails.application.routes.draw do
      resources :posts #追加
    end

5: 再度ターミナルからルーティングを確認する。(8つのルーティングが作成されていればOK)

    $ rails routes -g post
       Prefix Verb   URI Pattern               Controller#Action
        posts GET    /posts(.:format)           posts#index
              POST   /posts(.:format)           posts#create
     new_post GET    /posts/new(.:format)       posts#new
    edit_post GET    /posts/:id/edit(.:format)  posts#edit
         post GET    /posts/:id(.:format)       posts#show
              PATCH  /posts/:id(.:format)       posts#update
              PUT    /posts/:id(.:format)       posts#update
              DELETE /posts/:id(.:format)       posts#destroy

2.コントローラに7つのアクションを定義しよう

1: コントローラファイル(post_controller.rb)を確認し、以下の記述を行う。

    class PostsController < ApplicationController
      def index
        @posts = Post.all
      end
    
      def create
    
      end
    
      def new
    
      end
    
      def edit
    
      end

      def show

      end
    
      def update
    
      end
    
      def destroy
        
      end
    end

これで、ルーティングとコントローラの準備ができました。
ここからはそれぞれのアクションを実行していきます。

3. 7つのアクションを実行してみよう

アクションを実行する前にURI Pattern,Prefix,Controller#Action,Varbを理解していた方がスムーズに実行できます。

【index】(投稿一覧を表示する)
1: ターミナルからサーバーを立ち上げる。

rails s

2: ブラウザのアドレスバーにhttp://localhost:3000/postと入力し、indexアクションを実行してみる。

【show】(投稿詳細を表示する)
1: コントローラのshowアクションの中身を編集する。

  def show
    @post = Post.find(params[:id])
    #1件のみのデータ取得であるため、@postsではなく単数の@post
    #find(params[id])はURI(/post/:id)の:idと同じidのデータを@postから探す
  end

2: Viewフォルダの中にshow.html.erbを作成する。

app/views/post/show.html.erb

3: 1つの投稿を表示させるためのshow.html.erbファイルを編集する。

    <div>
        <label for="article_title">Title</label><br>
        <%= @post.title %> #1:で定義したインスタンス変数である@postのtitleを表示
    </div>
    
    <div>
        <label for="article_body">Body</label><br>
        <%= @post.body %> #1:で定義したインスタンス変数である@postのbodyを表示
    </div>

4: ブラウザにhttp://localhost:3000/posts/1と入力し、PostControllerのindexアクションを呼び出す。

show.html.erbのブラウザ表示画面

現段階では以下のようなテーブルが作成されるはずです。(idとtimestampsは自動生成)

id title body timestamps
1 投稿id_1のタイトル 投稿id_1の本文 id_1の作成日時
2 投稿id_2のタイトル 投稿id_2の本文 id_2 の作成日時
3 投稿id_3のタイトル 投稿id_3の本文 id_3の作成日時

:::

【new】・【create】(新規投稿を実装する)
1: コントローラのnewアクションを編集する。

  def new
    @post = Post.new
  end

2: Viewフォルダの中にnew.html.erbを作成する。

3: Form builderと言う機能を用いて、新規投稿を行うためのフォームを作成する。

    <%= form_with model: @post, url: posts_path, method: :post do |f| %>
      <div>
        <%= f.label :title, "タイトル" %><br>
        <%= f.text_field :title %>
      </div>
    
      <div>
        <%= f.label :body, "本文" %><br>
        <%= f.text_area :body %>
      </div>
    
      <div>
        <%= f.submit "投稿" %>
      </div>
    <% end %>

ひとまず一番上の行だけ理解しておけば良いかと思います。

    <%= form_with model: @post, url: posts_path, method: :post do |f| %>
    #form_with model: @post = どのモデルとデータをやり取りするかを記載
  #url: posts_path = PostControllerのCreateアクションが呼び出せるURIPathを記載
  #method: :post = HTTP VerbのPOSTを指定するための記載

4: http://localhost:3000/posts/newにアクセスして、ブラウザに表示されるかを確認する。

新規投稿フォーム

5: PostsControllerCreateアクションを編集し、ストロングパラメータを追加する。

    def create
        @post = Post.new(post_params)
        
        if  @post.save
          redirect_to post_path #redirect先のPathを指定
        else
          render :new
        end
    end
    ~~~
    ~~~
    private
        def post_params
          params.require(:post).permit(:title, :body)
        end
redirect_toとは(基礎編)

・指定のURL(HTTPリクエストメソッド)を実行する際に用いる。
・保存が完了し、別のページへ遷移させたいため、保存に成功した場合に用いる。
・処理の流れは、controller → URL → route → controller → viewとなるため、長い。

    redirect_to post_path #redirect先の指定
renderとは(基礎編)

・指定のビューファイルを表示する際に用いる。
・その前の画面をそのまま読み込むことができるため、保存に失敗した場合に用いる。
・処理の流れはcontroller → viewとなるため、短い。

    render :new #new.html.erbファイルを読み込んでという意味

6: http://localhost:3000/posts/newにアクセスし、投稿フォームを入力し投稿を押す。

投稿フォーム入力画面

7: 投稿が完了し、showページへ遷移している。

投稿詳細画面

【edit】・【update】(新規の編集と更新を実装する)
1: コントローラのeditアクションを編集する。

    def edit
        @post = Post.find(params[:id])
    end

2: Viewフォルダの中にedit.html.erbを作成する。

editのviewファイル作成画面

3: new.html.erbファイルの中身をコピーして貼り付け、以下のように編集する。

    <h1>Hello</h1>
    
    <%= form_with model: @post, url: post_path, method: :patch do |f| %>
      <div>
        <%= f.label :title, "タイトル" %><br>
        <%= f.text_field :title %>
      </div>
    
      <div>
        <%= f.label :body, "本文" %><br>
        <%= f.text_area :body %>
      </div>
    
      <div>
        <%= f.submit "更新" %>
      </div>
    <% end %>

一番上の行だけ理解しておけば良いかと思います。

    <%= form_with model: @post, url: posts_path, method: :pathch do |f| %>
    #form_with model: @post = どのモデルとデータをやり取りするかを記載
  #url: posts_path = PostControllerのupdateアクションが呼び出せるURIPathを記載
  #method: :patch = HTTP VerbのPATCHを指定するための記載

4: http://localhost:3000/posts/4/editにアクセスし、表示されるか確認する。

編集・更新画面
※まだ、更新ボタンを押しても更新はされない。

5: PostContollerupdateアクションの編集をする。

    def update
        @post = Post.find(params[:id]) 
        if @post.update(post_params) #post_paramsの値をアップデートする
          flash[:notice] = "編集が完了しました。"
          redirect_to post_path(@post.id) #redirect先の指定
        else
          flash[:alert] = "編集ができませんでした。"
          render :edit
        end
    end
:noticeと:alertオプションとは(応用編)

【:notice】
・noticeは何か通知を表示させたい場合に用いる。
・例えば、「ログインしました。」なと。
・コントローラファイルとは、以下のように記述する。

    flash[:notice] = "ログインしました。"

・ビューファイルでは、以下のように記述する。

   <%= notice %>

redirect_tonoticeを用いる場合は以下のように記述する。

     redirect_to root_path, notice: "表示させたいメッセージ"

【:alert】
・alertは警告のメッセージを表示させたい場合に用いる。
・例えば、「パスワードを8文字以上に設定してください。」など。
・コントローラファイルとは、以下のように記述する。

    flash[:alert] = "ログインに失敗しました。"

・ビューファイルでは、以下のように記述する。

   <%= alert %>

redirect_toalertを用いる場合は以下のように記述する。

     redirect_to root_path, alert: "表示させたいメッセージ"

6: フォームの内容を編集し、更新ボタンを押す。

編集・更新完了画面

【delete】(新規の削除を実装する)
1: コントローラのdestroyアクションを編集する。

  def destroy
    @post = Post.find(params[:id])
    if @post.destroy
      flash[:notice] = "削除が完了しました。"
    else
      flash[:alert] = "削除に失敗しました。"
    end
    redirect_to posts_path
  end

2: ターミナルに以下のコマンドを実行する。

    yarn add @babel/plugin-proposal-private-methods @babel/plugin-proposal-private-property-in-object

※Babelという翻訳機をインストールする意味。

Babelプラグインとは(発展編)

・JavaScriptのコードをトランスパイル(ある言語から別の言語へ変換すること)する際に、Babelというツールを使用して特定の機能を有効にするためのBabelプラグインをインストールするもの。

・Babelがプライベートメソッドとプライベートプロパティの構文をサポートし、JavaScriptのコード内でこれらの機能を使用できるようになる。

@babel/plugin-proposal-private-methodsは、JavaScriptのクラス内でプライベートメソッド(他の部分からアクセスできないメソッド)を使用するためのプロポーザルをサポートするためのBabelプラグイン。

@babel/plugin-proposal-private-property-in-objectは、JavaScriptのオブジェクト内でプライベートプロパティ(他の部分からアクセスできないプロパティ)を使用するためのプロポーザルをサポートするためのBabelプラグイン。

3: show.html.erbファイル(投稿詳細)に「削除」ボタンを追加する。

    <h1>Hello</h1>
    
      <div>
        <label for="article_title">Title</label><br>
        <%= @post.title %>
      </div>
    
      <div>
        <label for="article_body">Body</label><br>
        <%= @post.body %>
      </div>

    #追加
     <div>
        <%= link_to "削除", post_path(@post), method: :delete, data: { confirm: "本当に削除しますか?" } %>
      </div>


削除ボタンの追加

4: 削除ボタンを押して投稿一覧に遷移した際に投稿が削除されているか確認する。

削除完了画面

5.まとめ

参考サイト

https://qiita.com/Tamitchao/items/771e64f4753ff541d444

https://developer.mozilla.org/ja/docs/Web/HTTP/Methods

https://railsdoc.com/rails_base

おわりに

今回、 プログラミング初学者がRailsアプリケーションを動かす際に必要な知識として、CRUD(Create,Read,Update,Delete)を学んだ。上記CRUDの7つのアクションの実装方法を応用することで、様々な機能を実装可能となる。

Discussion