Rails グループへの参加/退会
この続きです🏋🏻
要件
- 自分がグループオーナーでない場合は、グループ詳細画面に「Join this group」ボタンを表示させる
- 「Join this group」ボタンをクリックすると、グループに参加。
グループ一覧画面にメンバーの人数とグループ詳細画面のリストに参加したユーザとして表示される - 参加中のグループの場合は「Leave this group」でグループから抜けられる
完成
グループ一覧画面
グループ詳細画面
モデルの記述
has_many :users, through: :group_users, source: :user
def includesUser?(user)
group_users.exists?(user_id: user.id)
end
has_many :users, through: :group_users, source: :user
Group モデルが GroupUser モデルを通じて User モデルと関連していることを表す。
includesUser?(user)は、与えられたuserがグループのメンバーであるかどうかを判定するメソッドを記述。
group_usersテーブルから、user_idがuserのidと一致するレコードが存在するかどうかをチェック。存在する場合はtrueを、存在しない場合はfalseを返す!
ルーティングの記述
resources :groups, only: [:new, :index, :show, :create, :edit, :update] do
resource :group_users, only: [:create, :destroy]
end
group_idがあればOKなので、resourceでネストさせる。
以下のルーティングが追加された!
コントローラーの記述
rails g controller group_users
⇩
class GroupUsersController < ApplicationController
before_action :authenticate_user!
def create #①
group_user = current_user.group_users.new(group_id: params[:group_id])
group_user.save
redirect_to request.referer
end
def destroy #②
group_user = current_user.group_users.find_by(group_id: params[:group_id])
group_user.destroy
redirect_to request.referer
end
end
〜解説〜
①create
グループに参加するために、group_usersという中間テーブルにユーザーとグループの関連を作成するcreateアクション。
current_userを使用して、現在のユーザーを取得し、group_usersに.newメソッドで新しいレコードを作成。その際、group_idを渡して、どのグループに参加するかを指定している!
group_userオブジェクトを保存し、redirect_to request.refererで前にいたページに戻る。
②destroy
現在ログインしているユーザーが所属しているグループから退会するためのdestroyアクション。
ログインしているユーザーの group_users 関連付けを使用して、指定されたグループに関連付けられた group_userインスタンスをfind_byメソッドで検索。
destroy メソッドを使用して、 group_userを削除し、redirect_to request.refererで前にいたページに戻る。
ビューの記述
メンバー数を表示させる。
<%= group.group_users.count %>
ここで、グループ作成者も最初からメンバーに含むようにしたかったのですが、うまく実装できず、、
とりあえず要件にはないので、このまま行きます😣
参加中のメンバーを表示させる。
<% @group.users.each do |user| %>
<li style="list-style: none;"><%= user.name %></li>
<% end %>
@groupに参加している全てのユーザーの名前をリスト形式で表示。
usersという関連付けがあるため、@group.usersでグループに参加している全てのユーザーが取得でき、eachメソッドを用いて1つずつ処理しながら、その名前を表示している。
参加・退会ボタンを表示する。
表示させたいところへ以下の記述を追加!
<% if @group.is_owned_by?(current_user) %>
<%= link_to 'Edit', edit_group_path(@group), class: "btn btn-sm btn-success" %>
<% elsif @group.includesUser?(current_user)%>
<%= link_to 'Leave this group', group_group_users_path(@group), method: :delete, class: "btn btn-sm btn-danger" %>
<% else %>
<%= link_to 'Join this group', group_group_users_path(@group), method: :post, class: "btn btn-sm btn-success" %>
<% end %>
〜解説〜
@group.is_owned_by?(current_user)
ログインしているユーザーがそのグループのオーナーかどうかを判定
@group.includesUser?(current_user)
ログインしているユーザーがそのグループのメンバーかどうかを判定
これらの条件分岐を元に、以下のように表示を分けている!
ログインしているユーザーがそのグループのオーナーの場合、グループ情報を編集するための「Edit」ボタンを表示。
⇩
ログインしているユーザーがそのグループのメンバーの場合、グループから退会するための「Leave this group」ボタンを表示。
⇩
ログインしているユーザーがそのグループのメンバーでもオーナーでもない場合、グループに参加するための「Join this group」ボタンを表示。
この流れで実装できるはずです。
何か間違いなどあればぜひ教えていただけますと幸いです!
🌱参考にさせていただいた記事
Discussion