Extract payload building into dedicated classes

Separates notification payload construction from push delivery by
introducing DefaultPayload, EventPayload, and MentionPayload classes
that encapsulate the title, body, and URL generation for each
notification type.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Rosa Gutierrez
2026-01-21 19:07:04 +01:00
parent 05819f84a2
commit 1d2ed91e89
4 changed files with 119 additions and 92 deletions
@@ -0,0 +1,41 @@
class Notification::DefaultPayload
attr_reader :notification
delegate :card, to: :notification
def initialize(notification)
@notification = notification
end
def to_h
{ title: title, body: body, url: url }
end
private
def title
"New notification"
end
def body
"You have a new notification"
end
def url
notifications_url
end
def card_url(card)
Rails.application.routes.url_helpers.card_url(card, **url_options)
end
def notifications_url
Rails.application.routes.url_helpers.notifications_url(**url_options)
end
def url_options
base_options = Rails.application.routes.default_url_options.presence ||
Rails.application.config.action_mailer.default_url_options ||
{}
base_options.merge(script_name: notification.account.slug)
end
end
+55
View File
@@ -0,0 +1,55 @@
class Notification::EventPayload < Notification::DefaultPayload
include ExcerptHelper
private
def title
case event.action
when "comment_created"
"RE: #{card_title}"
else
card_title
end
end
def body
case event.action
when "comment_created"
format_excerpt(event.eventable.body, length: 200)
when "card_assigned"
"Assigned to you by #{event.creator.name}"
when "card_published"
"Added by #{event.creator.name}"
when "card_closed"
card.closure ? "Moved to Done by #{event.creator.name}" : "Closed by #{event.creator.name}"
when "card_reopened"
"Reopened by #{event.creator.name}"
else
event.creator.name
end
end
def url
case event.action
when "comment_created"
card_url_with_comment_anchor(event.eventable)
else
card_url(card)
end
end
def event
notification.source
end
def card_title
card.title.presence || "Card #{card.number}"
end
def card_url_with_comment_anchor(comment)
Rails.application.routes.url_helpers.card_url(
comment.card,
anchor: ActionView::RecordIdentifier.dom_id(comment),
**url_options
)
end
end
@@ -0,0 +1,20 @@
class Notification::MentionPayload < Notification::DefaultPayload
include ExcerptHelper
private
def title
"#{mention.mentioner.first_name} mentioned you"
end
def body
format_excerpt(mention.source.mentionable_content, length: 200)
end
def url
card_url(card)
end
def mention
notification.source
end
end
+3 -92
View File
@@ -1,6 +1,4 @@
class Notification::Push
include ExcerptHelper
attr_reader :notification
delegate :card, to: :notification
@@ -27,98 +25,11 @@ class Notification::Push
def build_payload
case notification.source_type
when "Event"
build_event_payload
Notification::EventPayload.new(notification).to_h
when "Mention"
build_mention_payload
Notification::MentionPayload.new(notification).to_h
else
build_default_payload
Notification::DefaultPayload.new(notification).to_h
end
end
def build_event_payload
event = notification.source
base_payload = {
title: card_notification_title(card),
url: card_url(card)
}
case event.action
when "comment_created"
base_payload.merge(
title: "RE: #{base_payload[:title]}",
body: comment_notification_body(event),
url: card_url_with_comment_anchor(event.eventable)
)
when "card_assigned"
base_payload.merge(
body: "Assigned to you by #{event.creator.name}"
)
when "card_published"
base_payload.merge(
body: "Added by #{event.creator.name}"
)
when "card_closed"
base_payload.merge(
body: card.closure ? "Moved to Done by #{event.creator.name}" : "Closed by #{event.creator.name}"
)
when "card_reopened"
base_payload.merge(
body: "Reopened by #{event.creator.name}"
)
else
base_payload.merge(
body: event.creator.name
)
end
end
def build_mention_payload
mention = notification.source
{
title: "#{mention.mentioner.first_name} mentioned you",
body: format_excerpt(mention.source.mentionable_content, length: 200),
url: card_url(card)
}
end
def build_default_payload
{
title: "New notification",
body: "You have a new notification",
url: notifications_url
}
end
def card_notification_title(card)
card.title.presence || "Card #{card.number}"
end
def comment_notification_body(event)
format_excerpt(event.eventable.body, length: 200)
end
def card_url(card)
Rails.application.routes.url_helpers.card_url(card, **url_options)
end
def notifications_url
Rails.application.routes.url_helpers.notifications_url(**url_options)
end
def card_url_with_comment_anchor(comment)
Rails.application.routes.url_helpers.card_url(
comment.card,
anchor: ActionView::RecordIdentifier.dom_id(comment),
**url_options
)
end
def url_options
base_options = Rails.application.routes.default_url_options.presence ||
Rails.application.config.action_mailer.default_url_options ||
{}
base_options.merge(script_name: notification.account.slug)
end
end