※ 初めて書いた記事ですので、間違い等あればご指摘いただけますと幸いです。
概要
通知機能を利用して、チーム機能に招待機能を実装する。
前提
- ユーザー機能を実装済み
- チーム機能を実装済み
- 通知機能を実装済み
参考記事
通知機能はこちらの記事を参考させていただきました。
【Rails】通知機能を誰でも実装できるように解説する【いいね、コメント、フォロー】
通知モデルの概要
以下、テーブル情報の例です。
visitor_id | visited_id | post_id | comment_id | action | checked |
---|---|---|---|---|---|
1 | 2 | nil | nil | follow | false |
1 | 2 | 3 | nil | like | false |
1 | 2 | nil | nil | comment | false |
- visitor_id:通知を送ったユーザーのID
- visited_id:通知を送られた(受け取る)ユーザーのID
- post_id:いいねされた投稿
- comment_id:投稿へのコメントID
- action:通知の種類(ここでは
follow
,like
,comment
) - checked:通知を確認したかどうか
この記事の招待機能の概要
チームに加入できるリンクが付いている通知を送る。
|visitor_id|visited_id|team_id|action|checked|
|:-:|:-:|:-:|:-:|:-:|:-:|
|1|2|1|invitaion|false|
-
上記のようなテーブル情報を持つ通知を生成し、通知一覧に表示させる。
-
通知に記載されているリンクを踏むと招待されたチームに加入する。
このような流れでチームへの招待を実装します。
実装の手順
- ルーティングを設定。(config/routes.rb)
- 通知生成用のメソッドを作成。(app/models)
- コントローラに処理を記述。(app/controllers)
- フォームを記述。(app/views)
本記事ではこの順番で実装を進めていきます。
実装
- ルーティングの設定。
resources :teams, only: [:index, :show, :new, :create, :edit, :update] do
get :join
post :invitation
end
招待通知を生成するためのアクションinvitation
。
チームに加入する処理を行うアクションjoin
。
上記の2つのアクションのルーティングを記述します。
- 通知生成用のメソッドを作成。
def team_invitation_notification(current_user, visited_id, team_id)
# すでに招待用の通知が送られているか検索。
temp = Notification.where(visitor_id: current_user.id, visited_id: visited_id, team_id: team_id)
# 上記で検索した通知がない場合のみ、通知レコードを作成。
if temp.blank?
notification = current_user.active_notifications.new(
visited_id: visited_id,
team_id: team_id,
action: "invitation",
)
# エラーがなければ、通知レコードを保存。
notification.save if notification.valid?
end
end
end
- コントローラに処理を記述。
招待通知生成の処理を行うinvitation
アクションを記述。
def invitation
@team = Team.find(params[:id])
# この後 view に設置するフォームの値を参照する。
@user = User.find_by(id: params[:user_id])
notification = Notification.where(visited_id: @user.id, team_id: @team.id, action: "invitation")
unless notification.exists?
# それぞれの仮引数を置き換えて、team.rb に記述したメソッドを呼び出す。
@team.team_invitation_notification(current_user, @user.id, @team.id)
# 遷移する前のURLを取得し、リダイレクトさせる。
redirect_to request.referer, notice: "招待を送りました。"
else
redirect_to request.referer, alert: "すでに招待しています。"
end
end
チーム加入処理を行うjoin
アクションを記述。
def join
@team = Team.find(params[:id])
# @team.users に、current_user のレコードが含まれていなければ以下の処理を行う。
unless @team.users.include?(current_user)
# @team.users に、current_user のレコードを追加する。
@team.users << current_user
# 招待通知を検索して削除。
notification = Notification.find_by(visited_id: current_user.id, team_id: @team.id, action: "invitation")
notification.destroy
end
redirect_to team_path(@team), notice: "チームに参加しました。"
end
- フォームを記述。
# @other_users は、チームに所属していないユーザーの値を取得している。
<% if @other_users.exists? %>
<%= form_with model: @user, url: invitation_team_path(@team), method: :post, local: true do |f| %>
<%= f.collection_select :user_id, @other_users, :id, :nickname %>
<%= f.submit "招待する" %>
<% end %>
<% end %>
- 実際に表示される通知を記述。
action
カラムの値によって表示する内容を変えるようにしたいので、case
文を使って表示を分岐させます。
<% case notification.action %>
<% when "invitaion" %>
<%= link_to "visitor.name", user_path(visitor) %>
さんからチームへの招待が届きました。
# このリンクをクリックすると、チーム加入処理を行う join アクションが働く。
<%= link_to "参加する", team_join_path(notification.team_id) %>
以下の記述は、`<% if notification.action == "invitation" %>`と同義です。
<% case notification.action %>
<% when "invitaion" %>
通知機能のように、分岐が多い場合にはcase
文を用いる方が良いと思います。
実装の工程は以上です。
お疲れ様でした。
初学者が考えた程度のものですので、足りないところが多々あるかと存じますが、どなたかのお役に立てば幸いです。