如何发送带有创建决斗的姓名的通知?
现在两个dueler's
都会收到通知,但通知中列出了自己的名称notification.dueler.user.name
模型
class Dueler < ActiveRecord::Base
belongs_to :user
belongs_to :challenge
belongs_to :duel
after_save :create_notification
has_many :notifications
private
def create_notification
notifications.create(
duel: duel,
user: user, # I'm not sure if or how to rewrite this line so that the notification shows the user's name who created the duel.
read: false
)
end
end
通知
<%= link_to notification.dueler.user.name, user_path(notification.dueler.user_id) %> challenged you to a <%= link_to "duel", notification_duel_request_path(notification, notification.duel_id) %>
rails c
Notification.find(223)
id: 223,
user_id: 2, # This is who created the duel
duel_id: 112,
dueler_id: 181>
Notification.last
id: 224,
user_id: 114,
duel_id: 112,
dueler_id: 182>
Duel.last
id: 112,
Dueler.find(181)
id: 181,
user_id: 2,
challenge_id: 302,
duel_id: 112,
Dueler.last
id: 182,
user_id: 114,
challenge_id: 410,
duel_id: 112,
答案 0 :(得分:1)
您的Dueler课程是否真的要负责通知其他参与者? - 我不这么认为。在这种情况下,它只是一个m2m的连接模型。
此外,您的模型不知道会话 - 因此它不知道两个应答者中的哪一个实际创建了决斗。虽然您可以查看duel.user
,但您可能正在制作鸡蛋与鸡蛋的情景。
相反,你可能想要选择一个更理智和解耦的解决方案,而不是将所有模型变成浓稠的汤。
class User < ActiveRecord::Base
has_many :duelers
has_many :duels, through: :duelers
has_many :notifications
end
class Duel < ActiveRecord::Base
has_many :duelers
has_many :users, through: :duelers
end
class Dueler < ActiveRecord::Base
enum role: [:defendant, :challenger]
belongs_to :user
belongs_to :duel
end
class Notification < ActiveRecord::Base
enum status: [:unread, :read, :trashed]
belongs_to :user
end
此处,您的通知类不必了解Dueler
,Duel
或任何游戏逻辑。它只需要收件人和消息并完成其工作。
假设您在users#show
页面上有一个离散的表单来创建决斗:
<%= button_to( "Challenge to a duel", user_duels_path(user_id: @user.to_param), method: :post) %>
采取以下行动:
class Users::DuelsController < ApplicationController
before_action :set_user
# POST users/:user_id/duels
def create
@duel = Duel.new do |d|
d.duelers.new(user: current_user, role: :challenger)
d.duelers.new(user: @user, role: :defendant)
end
if @duel.save
DuelNotifier.new(current_user, @user).send
redirect_to @duel
else
redirect_to @user, alert: 'Duel could not be created'
end
end
private
def set_user
@user = User.find(params[:user_id])
end
end
在应用程序通知中创建内容时,您不希望在模型层上执行此操作:
而是从邮寄者的工作方式中获取一些线索:
# app/notifiers/duel_notifier.rb
class DuelNotifier
attr_accessor :challenger, :defendant
def initialize(challenger, defendant)
@challenger, @defendant = challenger, defendant
end
def send
[].tap do |a|
a.push( @challenger.notifications.create!(
message: "You have challenged to #{defendant.name} to a duel."
) )
a.push( @defendant.notifications.create!(
message: "#{challenger.name} has challenged you to a duel."
) )
end
end
end
这只是一个完成一项工作的简单课程。我们可以通过简单直接的方式对此进行测试:
RSpec.describe DuelNotifier do
let(:challenger) { create(:user) }
let(:defendant) { create(:user) }
let(:notifier) { described_class.new(challenger, defendant) }
it "creates two notifications" do
expect { notifier.send }.to change(Notification, :count).by(+2)
end
it "creates the correct notification for the challenger" do
notifier.send
expect(challenger.notifications.last.message).to eq(
"You have challenged to #{defendant.name} to a duel."
)
end
it "creates the correct notification for the defendant" do
notifier.send
expect(defendant.notifications.last.message).to eq(
"#{challenger.name} has challenged you to a duel."
)
end
end