1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails】Rails APIを用いたグループ機能実装:グループ作成とユーザーの入退会処理

Posted at

Rails APIでUser周りの実装をしたので、グループの作成とユーザーの入退会処理をしていきます。
【Rails】JWTを用いたUser周りのAPI実装

Groupテーブル

カラム名 データ型 制約 説明
id integer 主キー、オートインクリメント グループの一意な識別子
name string null: false グループ名
created_at datetime null: false レコード作成日時
updated_at datetime null: false レコード更新日時

GroupMembershipテーブル

カラム名 データ型 制約 説明
id integer 主キー、オートインクリメント グループメンバーシップの一意な識別子
user_id integer null: false, foreing ket (users.id) ユーザーID(ユーザーへの外部キー)
group_id integer null: false, foreing ket (groups.id) グループID(グループへの外部キー)
created_at datetime null: false レコード作成日時
updated_at datetime null: false レコード更新日時

ルーティング

グループの作成、更新、削除、参加、退会を実装していきます。

HTTPメソッド パス コントローラ#アクション 説明
POST /api/v1/groups groups#create グループを新規作成
PUT/PATCH /api/v1/groups/:id groups#update グループ情報を更新
DELETE /api/v1/groups/:id groups#destroy グループを削除
POST /api/v1/groups/:id/join group_memberships#create 指定したグループに参加
DELETE /api/v1/groups/:id/leave group_memberships#destroy 指定したグループから退会

以下がルーティングです

routes.rb
resources :groups do
  member do
    post 'join', to: 'group_memberships#create'
    delete 'leave', to: 'group_memberships#destroy'
  end
end

期待するレスポンス

  • POST /api/v1/groups
json
{
  "message": "グループが作成されました。",
  "group": {
    "id": 1,
    "name": "新しいグループ",
    "created_at": "2024-11-03T12:34:56Z",
    "updated_at": "2024-11-03T12:34:56Z"
  }
}
  • PUT/PATCH /api/v1/groups
json
{
  "message": "グループ情報が更新されました。",
  "group": {
    "id": 1,
    "name": "更新されたグループ",
    "created_at": "2024-11-03T12:34:56Z",
    "updated_at": "2024-11-03T12:45:00Z"
  }
}
  • DELET /api/v1/groups
json
{
  "message": "グループが削除されました。"
}
  • POST /api/v1/join
json
{
  "message": "グループに参加しました。",
  "group_membership": {
    "id": 1,
    "user_id": 1,
    "group_id": 1,
    "created_at": "2024-11-03T12:34:56Z"
  }
}
  • DELETE /api/v1/leave
json
{
  "message": "グループから退会しました。"
}

Groupテーブルの作成

マイグレーションの作成

docker-compose run web rails generate model Group name:string

このコマンドにより、Groupテーブルのマイグレーションファイルが生成されます。nameカラムが追加されます。

マイグレーションの実行

docker-compose run web rails db:migrate

これでGroupテーブルがデータベースに作成されます。

モデルの編集

groupのレコードが削除された時に関連するgroup_membershipsのレコードも同時に削除するように設定。

group_group.rb
class Group < ApplicationRecord
  has_many :group_memberships, dependent: :destroy
  has_many :users, through: :group_memberships
end

GroupMembershipテーブルの作成

マイグレーションの作成

docker-compose run web rails generate model GroupMembership user:references group:references

このコマンドにより、GroupMembershipテーブルのマイグレーションファイルが生成されます。user_id、group_idカラムが追加されます。
user_idとgroup_idの2つの外部キーが必要です。

マイグレーションの実行

docker-compose run web rails db:migrate

これでGroupテーブルがデータベースに作成されます。

バリデーションの追加

同じユーザーが同じグループに重複して参加できないようにするためにバリデーションを追加します。

group_membership.rb
class GroupMembership < ApplicationRecord
  belongs_to :user
  belongs_to :group

  validates :user_id, uniqueness: { scope: :group_id }
end

マイグレーションの実行

docker-compose run web rails db:migrate

これでGroupMembershipテーブルがデータベースに作成されます。

userモデルの編集

userのレコードが削除された時に関連するgroup_membershipsのレコードも同時に削除するように設定。

user.rb
  has_many :group_memberships, dependent: :destroy
  has_many :groups, through: :group_memberships

コントローラの作成

groupsコントローラ

docker-compose exec web rails generate controller api/v1/Groups
groups_controller.rb
module Api
  module V1
    class GroupsController < ApiController
      before_action :authenticate_user
      before_action :set_group, only: [:update, :destroy]

      # グループを新規作成
      def create
        group = Group.new(group_params)
        if group.save
          GroupMembership.create(user: current_user, group: group)
          render json: { message: "グループが作成されました。", group: { id: group.id, name: group.name } }, status: :created
        else
          render json: { errors: group.errors.full_messages }, status: :unprocessable_entity
        end
      end

      # グループ情報を更新
      def update
        if @group.update(group_params)
          render json: { message: "グループ情報が更新されました。", group: {id: @group.id, name: @group.name} }, status: :ok
        else
          render json: { errors: @group.errors.full_messages }, status: :unprocessable_entity
        end
      end

      # グループを削除
      def destroy
        if @group.destroy
          render json: { message: "グループが削除されました。" }, status: :ok
        else
          render json: { error: "グループの削除に失敗しました。" }, status: :unprocessable_entity
        end
      end

      private

      # Strong Parameters
      def group_params
        params.require(:group).permit(:name)
      end

      # グループを取得
      def set_group
        @group = current_user.groups.find(params[:id])
      rescue ActiveRecord::RecordNotFound
        render json: { error: "グループが見つかりません。" }, status: :not_found
      end
    end
  end
end

group_membersipsコントローラ

docker-compose exec web rails generate controller api/v1/GroupMemberships
group_memberships_controller/rb
module Api
  module V1
    class GroupMembershipsController < ApiController
      before_action :authenticate_user

      # グループに参加
      def create
        group = Group.find(params[:id])
        membership = current_user.group_memberships.build(group: group)

        if membership.save
          render json: { message: "グループに参加しました。" }, status: :created
        else
          render json: { errors: membership.errors.full_messages }, status: :unprocessable_entity
        end
      end

      # グループから退会
      def destroy
        membership = current_user.group_memberships.find_by(group_id: params[:id])

        if membership&.destroy
          render json: { message: "グループから退会しました。" }, status: :ok
        else
          render json: { error: "退会に失敗しました。" }, status: :unprocessable_entity
        end
      end
    end
  end
end

Postmanを使ってリクエスト

Postmanを使ってそれぞれリクエストを送ってみます。

グループ作成

リクエストメソッドをPOSTに設定しURLを以下に設定する

http://localhost:3000/v1/groups

リクエストボディを以下のように設定して

json
{
  "name": "hoge group"
}

リクエストを送ると以下のレスポンスが返ってきます。

json
{
    "message": "グループが作成されました。",
    "group": {
        "id": 1,
        "name": "hoge group"
    }
}

グループ情報更新

リクエストメソッドをPATCHに設定しURLを以下に設定する

http://localhost:3000/v1/groups/1

リクエストボディを以下のように設定して

json
{
  "name": "fuga group"
}

リクエストを送ると以下のレスポンスが返ってきます。

json
{
    "message": "グループ情報が更新されました。",
    "group": {
        "id": 1,
        "name": "fuga group"
    }
}

グループ情報更新

リクエストメソッドをPATCHに設定しURLを以下に設定する

http://localhost:3000/v1/groups/1

リクエストボディを以下のように設定して

json
{
  "name": "fuga group"
}

リクエストを送ると以下のレスポンスが返ってきます。

json
{
    "message": "グループ情報が更新されました。",
    "group": {
        "id": 1,
        "name": "fuga group"
    }
}

グループ削除

リクエストメソッドをDELETに設定しURLを以下に設定する

http://localhost:3000/v1/groups/1

リクエストボディは設定せずにリクエストを送ると以下のレスポンスが返ってきます。

json
{
    "message": "グループが削除されました。"
}

グループ退会

リクエストメソッドをDELETに設定しURLを以下に設定する

http://localhost:3000/v1/groups/1/leave

リクエストボディは設定せずにリクエストを送ると以下のレスポンスが返ってきます。

json
{
    "message": "グループから退会しました。"
}
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?