前提・実現したいこと
プログラミングスクールに通うプログラミング初心者です。
現在、ruby on rails でイベント投稿アプリを開発しています。
このイベント投稿アプリでは、DM機能があります。
今回は、DMをしたらDMをされた人に通知がいくようなシステムを作りたいと考えています。
また、こちらのリンクをほとんど同じように参考にさせていただきました。
DM通知機能の参考
しかし、ある程度の意味を理解し参考通りに実装したつもりだったのですが、エラーが出てしまいました。
(通知機能のindexページにアクセスしたところでエラー)
発生している問題・エラーメッセージ
NoMethodError in Notifications#index undefined method `visitor' for #<Notification::ActiveRecord_AssociationRelation:0x00007f963a925720> Extracted source (around line #1): <% visitor = notification.visitor %> #ここでエラー <% visited = notification.visited %> <div> <%= link_to user_path(visitor) do %> <%= visitor.name %>さんが <% end %>
該当のソースコード
(routes.rb)
Rails.application.routes.draw do get 'notifications/index' devise_for :users root to: 'home#top' resources :users resources :events do resources :comments, only: :create resources :entries, only: [:index, :new, :create] resource :favorites, only: [:create, :destroy] collection do get 'search' end end resources :messages, only: :create resources :rooms, only: [:create, :show] resources :notifications, only: :index #通知機能 end
通知機能ののマイグレーションファイルです。
class CreateNotifications < ActiveRecord::Migration[6.0] def change create_table :notifications do |t| t.integer :visitor_id t.integer :visited_id t.integer :room_id t.integer :message_id t.string :action t.boolean :checked t.timestamps end end end
(messages.controller.rb)チャットのメッセージのコントローラーです。
class MessagesController < ApplicationController before_action :authenticate_user! def create if Invite.where(user_id: current_user.id, room_id: params[:message][:room_id]).present? @message = Message.new(message_params) @room = @message.room if @message.save @roommembernotme = Invite.where(room_id: @room.id).where.not(user_id: current_user.id) @theid=@roommembernotme.find_by(room_id: @room.id) notification = current_user.active_notifications.new( room_id: @room.id, message_id: @message.id, visited_id: @theid.user_id, visitor_id: current_user.id, action: 'dm' ) if notification.visitor_id == notification.visited_id notification.checked = true end notification.save if notification.valid? redirect_to "/rooms/#{@message.room_id}" end else redirect_back(fallback_location: root_path) end end private def message_params params.require(:message).permit(:user_id, :body, :room_id).merge(user_id: current_user.id) end end
(notifications_controller.rb)通知機能のコントローラーです。
class NotificationsController < ApplicationController def index @notifications = current_user.passive_notifications end end
(user.rb)ユーザーモデルです。#関係ないところは省略してます。
has_many :active_notifications, class_name: 'Notification', foreign_key: 'visitor_id', dependent: :destroy has_many :passive_notifications, class_name: 'Notification', foreign_key: 'visited_id', dependent: :destroy
(message.rb)メッセージのモデル
class Message < ApplicationRecord belongs_to :user belongs_to :room has_many :notifications, dependent: :destroy end
(room.rb)チャットルームのモデルです。
class Room < ApplicationRecord has_many :messages, dependent: :destroy has_many :invites, dependent: :destroy has_many :notifications, dependent: :destroy end
notification.rb通知機能のモデルです。
class Notification < ApplicationRecord default_scope -> { order(created_at: :desc) } belongs_to :room, optional: true belongs_to :message, optional: true belongs_to :visitor, class_name: 'User', foreign_key: 'visitor_id', optional: true belongs_to :visited, class_name: 'User', foreign_key: 'visited_id', optional: true end
(notifications/index.html.erb)通知機能のトップページ
<% notifications = @notifications.where.not(visitor_id: current_user.id) %> <% if notifications.exists? %> <%= render 'notifications', notification: notifications %> <% else %> <p>通知はございません</p> <% end %>
(notifications/_notifications.html.erb)通知機能のトップページ(render)
<% visitor = notification.visitor %> <% visited = notification.visited %> <div> <%= link_to user_path(visitor) do %> <%= visitor.name %>さんが <% end %> <% if notification.action=='dm' %> あなたにDMを送りました <% end %> </div>
試したこと
エラーメッセージから、visitorが定義されていないと判断したが、visitorを持ってくるには定義が必要なのかどうかが、わかりません。参考にさせていただいたサイトでは、特に定義を書いているようには見えなかったため定義は必要ないと考えました。
また、通知機能のコントローラーでbinding.pryをかけてみたところ
class NotificationsController < ApplicationController
def index
@notifications = current_user.passive_notifications
binding.pry
end
end
[1] pry(#<NotificationsController>)> params
=> <ActionController::Parameters {"_method"=>"get", "authenticity_token"=>"tNMX58xTfELHDEdSlTuCpjc4QxTvS6uPQ39lRwnFEUkgk3n1RjhgEhZorQk+Bo1Xn8a6MnWEOWjuOPbT65XyYA==", "controller"=>"notifications", "action"=>"index"} permitted: false>
[2] pry(#<NotificationsController>)> @notifications
Notification Load (0.6ms) SELECT notifications
.* FROM notifications
WHERE notifications
.visited_id
= 1 ORDER BY notifications
.created_at
DESC
↳ app/controllers/notifications_controller.rb:4:in `index'
=> [#<Notification:0x00007ff051c63010
id: 1,
visitor_id: 3,
visited_id: 1,
room_id: 4,
message_id: 26,
action: "dm",
checked: nil,
created_at: Tue, 02 Mar 2021 14:51:28 UTC +00:00,
updated_at: Tue, 02 Mar 2021 14:51:28 UTC +00:00>]
と出ました。メッセージコントローラーを移動して、通知コントローラーが動くため、コントローラーには問題はなく
コントローラーからビューの間でデータの受け渡しができていないと仮説は立てました。
しかし、定義しないといけないものがわかりませんでした。
ご教授いただければ幸いです。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。