4
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?

More than 1 year has passed since last update.

Rails6で通知機能を実装(ポリモーフィック)手直し版

Last updated at Posted at 2022-09-06

前回投稿した通知機能をポリモーフィックを使って実装しましたが、途中からうまく使えていませんでした。
下記記事のenumの設定から分岐してviewまでを修正して書いていきます。
この記事から見られた場合はenumまでは下記記事を見てください

enumの設定

model/activity.rb
  enum action_type: {
    favorited_the_diary:      0,
    followed_you:             1,
    commented_on_the_diary:   2
  }

通知する内容をなんとなく翻訳にかけて分かるように書いてあります
後で日本語化するので単語一個だと分かりにくくなります

create時に通知を入れる

通知したい内容がcreateされたときにactivityをcreateするようにします

model / favorite.rb comment.rb relationship.rb
after_create_commit :create_activities

private

def create_activities
  Activity.create!(subject: self, user_id: ユーザーのID, action_type: Activity.action_types[:enumで設定した内容])
end

各モデルにafter_create_commitを入れます
これはDB保存が完了した時をトリガーに動きます
詳しくはRailsガイドをみてください

今回入れたい通知は保存したタイミングで大丈夫ですが内容によって好きなタイミングでcreate_activityが動くように書いてください


create_activitiesの説明

  • subject: self
    これでDB保存ができた内容がはいります(typeとid)

  • user_id: ユーザーのID
    DB保存した内容からuser_idを取り出して書いてください
    例:いいねのとき
    user_id: diary.user.id(いいねに紐づいてる投稿に紐づいてるユーザーのID)

  • action_type: Acticity.action_types[:enumで設定した内容]
    右で書いた文はenumで設定した内容から値を出力しています
    例:いいねのとき
    action_type: Activity.action_types[:favorited_the_diary]これでaction_typeに0が入ります

ターミナルで確認してみます
いいねが保存された後にcreate_activitiesが動いて保存されたのが確認できます
ここで正確に保存が出来ているか確認してください
image.png
※user_idがいいねとアクティビティで同じ値なのは自分の投稿をいいねしたためです

コントローラーとルーティングの設定

ここからは好きなように書いて問題ありません
未読だけ表示、同じ投稿へのいいねはまとめる、どのタイミングで見たことにするのか、いろいろカスタマイズしてください

ここではすべての通知の一覧表示と一覧表示から各通知を押したときに既読にする設定で実装しています
viewファイルのすべては書きません、レイアウトは頑張ってください

rails g でコントローラーを作って設定していきます

activities_controller.rb
class Public::ActivitiesController < ApplicationController
  before_action :authenticate_user

  def index
    @activities = current_user.activities.order(created_at: :desc).page(params[:page]).per(20)
  end

  def read
    activity = current_user.activities.find(params[:id])
    unless activity.read?
      activity.update(read: true)
    end
    redirect_to activity.subject.redirect_path
  end

コントローラーの説明

  • before_action :authenticate_user
    deviseのメソッドでユーザー以外をはじきます

  • index
    表示したい内容をkaminariを使って20件ずつ作成日時の新しい順でいれます

  • read
    通知一覧から各通知をクリックした際にすべてここを通して処理します
    通知を読んだらtrueにして各通知元へリダイレクトさせます

  • redirect_to activity.subject.redirect_path
    ここでsubjectにモデルの情報が入っているので、モデルにあるインスタンスメソッドを呼び出します
    ポリモーフィック設定でcaseやifを使わずに分岐させることが出来ます

モデルにredirect_pathを書いていきます

model/favorite.rb comment.rb relationship.rb
  def redirect_path
    #コメントの場合
    "/#{diary.user.name_id}/diaries/#{diary.id}"
  end

Rrefixで書けないためURLで書きます
#{}でかこうことで変数展開ができます
好きなリダイレクト先を入れてください。


routes.rb
  resources :activities, only: [:index] do
    patch :read, on: :member
  end

resurcesに読んだ時の処理をするルートをネストで入れてます

viewの作成

最低限の表示だけ書いています

activities/index.html.erb
<% if @activities.present? %>
  <% @activities.each do |activity| %>
    <%= link_to read_user_activity_path(current_user.name_id,activity), method: :patch do %>
      <%= @activity.subject.name %>さんが<%= @activity.action_type_i18n %>
    <% end %>
  <%= paginate @activities %>
  <% end %>
<% else %>
  <p>通知はありません</p>
<% end %>

ここでもポリモーフィックの利点である同じコードでモデルごとに違う内容を表示します。
subject.nameと書きましたがnameカラムがないモデルもあります
モデルにインスタンスメソッドを書きます

model/comment.rb favorite.rb relationship.rb
  def name
    #favorite.rbの場合
    user.name
  end

enumの日本語化

activityのaction_typeを日本語化して表示させます
詳しくはrails日本語化で検索するとたくさん出てきます
下記方法でできなかったら調べてみてください

application.rbに日本語化の文を書きます

config/application.rb
module NaganoCake
  class Application < Rails::Application  
  :
  
  config.i18n.default_locale = :ja

  :
  end
end

ja.ymlファイルを作って下記を書きます

config/locales/ja.yml
ja:
  enums:
    activity:
      action_type:
        favorited_the_diary: "投稿にいいねしました"
        followed_you: 'あなたをフォローしました'
        commented_on_the_diary: '投稿にコメントしました'

以上で日本語になります
rails cでコンソールを開いて確認することが出来ます
action_typeに_i18nをつけると日本語で表示されます
image.png

実装は以上です
表示できましたでしょうか

まとめ

今回は通知機能をポリモーフィックを使って実装していきました
メソッドをそろえることでコードを変えずに表示を変えることが出来ます。

通知機能をいれるために覚えておくこと

  • 通知用でモデルが必要
  • 任意のタイミングで通知モデルをcreate

ポリモーフィックで覚えておくこと

  • モデル情報ごと保存することが出来る

最後に

通知機能をポリモーフィックで作りましたが、ポリモーフィックで得られるメリットを最大限にすることを目的でコードをつくりました。redirect_pathは正直controllerにまとめて書いておいてもいいかなと思います。

polimorphic_pathという書き方もあるのですが私はrouteを変にカスタマイズしたせいで使えませんでした。確実にできる方法で書いてあります。興味のある方は調べてみてください。

ポリモーフィック自体はしっかり使えると便利だと思うので使いどころを考えていきたいですね。

いろんな書き方ができるため、どの方法が一番いいのかの判断をできるようにしたいです。

4
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
4
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?