🌅

Rails(APIモード)で基本のCRUDをおさらいする

2024/02/18に公開

はじめに

  • 最近、業務の方でRubyonRailsを全く触れていなかった、、(そもそも所謂webアプリケーション自体に触れられていなかった)
  • 久しぶりに触ったらかなり忘れていた汗
  • 思いとしてRubyonRailsもっとやっていきたいので個人開発でRailsで何か作ろうと考えた
    • 知識定着のため、記事にできたらいいな〜と思い立ってこの記事を書いてます(今更みたいな内容ばかりですがきっと忘れる将来の自分の向けて書く所存、、)

早速APIを作る

必要な作業として思い当たるのが

  • モデル作成
  • DBマイグレーション
  • コントーローラー作成
    • CRUD操作するための各メソッド記述
  • ルーティング記述
  • 実際にapiを叩いて確認

以上がパッと思い浮かんだこと。

モデル作成

$ rails g model LocationPost

生成されたモデルのファイルは以下
location_post.rb

class LocationPost < ApplicationRecord
    validates :title, presence: true
end

DBマイグレーション(カラム追加修正含む)

モデル作成のタイミングで作成されたマイグレーションファイルclass CreateLocationPosts <

0231009111424_create_location_posts.rb

ActiveRecord::Migration[7.0]
  def change
    create_table :location_posts do |t|
      t.string :title
      t.text :description
      
      t.timestamps
    end
  end
end

DBマイグレーション

$ rails db:migrate

カラムを追加したくなったのでテーブルにカラムを追加する

$ rails g migration AddAddressToLocationPost

再びDBマイグレーション

$ rails db:migrate

20240215131331_add_address_to_location_post.rb

class AddAddressToLocationPost < ActiveRecord::Migration[7.0]
  def change
    add_column :location_posts, :address, :string
  end
end

コントローラー作成

$ rails g contoller api/v1 LocationPosts

生成されたコントローラーのファイルは以下
location_posts_contoller.rb

class Api::V1::LocationPostsController < ApplicationController

end

CRUD操作するための各メソッド記述

GET(index,show)

class Api::V1::LocationPostsController < ApplicationController

    def index
        # LocationPostのレコード全取得
        @location_posts = LocationPost.all
        # 取得したレコードをJSON形式で返す
        render json: @location_posts, status: :ok
    end

    def show
        # クライアントより渡されたパラメーター`id`の値を用いて検索したレコードを取得
        @location_post = LocationPost.find(params[:id])
        # 取得したレコードをJSON形式で返す
        render json: @location_post, status: :ok
    end

end

POST(create)

class Api::V1::LocationPostsController < ApplicationController
~
    def create
        # クライアントからのリクエストパラメータを取得
        @location_post = LocationPost.new(location_post_params)
        # レコードをDBに保存
        if @location_post.save
            # 保存が成功した場合は作成したレコードをJSON形式で返す
            render json: @location_post, status: :ok
        else
            # 保存が失敗した場合はエラーを返す
            render json: @location_post.errors, status: :bad_request
        end
    end
~
    private
            # ストロングパラメータを設定
            def location_post_params
                params.require(:location_post).permit(:title, :description, :address)
            end
    end
end

ストロングパラメータに関しては以下が勉強になりました
https://qiita.com/ozackiee/items/f100fd51f4839b3fdca8

PUT(update)

class Api::V1::LocationPostsController < ApplicationController
~
    def update
        # クライアントより渡されたパラメーター`id`の値を用いて検索したレコードを取得
        @location_post = LocationPost.find(params[:id])
        # クライアントからのリクエストパラメータを取得しその値を用いてレコードをアップデート
        if @location_post.update(location_post_params)
            # 更新が成功した場合、更新したレコードをJSONで返す
            render json: @location_post, status: :ok
        else
            # 更新が失敗した場合はエラーを返す
            render json: @location_post.errors, status: :bad_request
        end
    end
~
    private
        def location_post_params
            params.require(:location_post).permit(:title, :description, :address)
        end
end

DELETE(destroy)

class Api::V1::LocationPostsController < ApplicationController
~  
    def destroy
        # クライアントより渡されたパラメーター`id`の値を用いて検索したレコードを取得
        @location_post = LocationPost.find(params[:id])
        # 対象のレコードを削除
        if @location_post.destroy
            # 削除が成功した場合は削除したレコードをJSONで返す
            render json: @location_post, status: :ok
        else
            # 削除失敗の場合はエラーを返す
            render json: { error: 'Failed to delete resource' }, status: :unprocessable_entity
        end
    end
~

before_actionを設定

いくつかのメソッドで以下を書いていますが共通化できるのでbefore_actionにて設定

@location_post = LocationPost.new(location_post_params)
class Api::V1::LocationPostsController < ApplicationController
    before_action :set_location_post, only: [:show, :update, :destroy]
~
    private
        # private内に追加
        def set_location_post
            @location_post = LocationPost.find(params[:id])
        end
~
end

create,update,destroyで記述されている共通部分は削除

ルーティング記述

routes.rb

Rails.application.routes.draw do
  namespace :api do
    namespace :v1 do
      # 今回作成したメソッドを設定
      resources :location_posts, only: [:index, :show, :create, :update, :destroy]
    end
  end
end

ルーティングを確認
以下パスにブラウザよりアクセス(今回3001ポートでrailsサーバーを起動)

http://localhost:3001/rails/info/routes

実際にapiを叩いて確認

Postmanを使って確認していきます

GET(index,show)

index

  • http://localhost:3001/api/v1/location_posts/

show

  • http://localhost:3001/api/v1/location_posts/:id
  • paramsよりkeyid,value1を指定(参照する値のid)

POST(create)

  • http://localhost:3001/api/v1/location_posts
  • body/rawより作成するレコードの値をJSONで記述

PUT(update)

  • http://localhost:3001/api/v1/location_posts/:id
  • paramsよりkeyid,value1を指定
  • body/rawより更新するレコードの値をJSONで記述

DELETE(destroy)

  • http://localhost:3001/api/v1/location_posts/:id
  • paramsよりkeyid,value1を指定(削除するidの値)

実際のコード

location_posts_contoller.rb

class Api::V1::LocationPostsController < ApplicationController
    before_action :set_location_post, only: [:show, :update, :destroy]

    def index
        @location_posts = LocationPost.all
        render json: @location_posts, status: :ok
    end

    def show
        render json: @location_post, status: :ok
    end

    def create
        @location_post = LocationPost.new(location_post_params)
        if @location_post.save
            render json: @location_post, status: :ok
        else
            render json: @location_post.errors, status: :bad_request
        end
    end

    def update
        if @location_post.update(location_post_params)
            render json: @location_post, status: :ok
        else
            render json: @location_post.errors, status: :bad_request
        end
    end

    def destroy
        if @location_post.destroy
            render json: @location_post, status: :ok
        else
            render json: { error: 'Failed to delete resource' }, status: :unprocessable_entity
        end
    end

    private
        def set_location_post
            @location_post = LocationPost.find(params[:id])
        end

        def location_post_params
            params.require(:location_post).permit(:title, :description, :address)
        end
end

location_post.rb

class LocationPost < ApplicationRecord
    validates :title, presence: true
end

routes.rb

Rails.application.routes.draw do
  namespace :api do
    namespace :v1 do
      resources :location_posts, only: [:index, :show, :create, :update, :destroy]
    end
  end
end

終わりに

読んでくださった方ありがとうございました!

Discussion