From 4eb17c5a5fde6fc26be87579d2bf5b50e660063b Mon Sep 17 00:00:00 2001
From: Pablo Brasero
Date: Mon, 20 Apr 2026 15:26:48 +0100
Subject: [PATCH] Skeleton to implement each type of web notification
---
.rubocop_todo.yml | 2 +-
app/controllers/notifications_controller.rb | 4 ++
app/models/user.rb | 2 +
app/models/user_notifications.rb | 52 +++++++++++++++++++++
app/views/notifications/index.html.erb | 11 ++++-
test/factories/notifications.rb | 31 ++++++++++++
6 files changed, 100 insertions(+), 2 deletions(-)
create mode 100644 app/models/user_notifications.rb
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index f7565912e..892e927c0 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -56,7 +56,7 @@ Metrics/BlockNesting:
# Offense count: 23
# Configuration parameters: CountComments, CountAsOne.
Metrics/ClassLength:
- Max: 342
+ Max: 343
# Offense count: 72
# Configuration parameters: AllowedMethods, AllowedPatterns.
diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb
index a6a6fd4a7..602841383 100644
--- a/app/controllers/notifications_controller.rb
+++ b/app/controllers/notifications_controller.rb
@@ -9,4 +9,8 @@ class NotificationsController < ApplicationController
authorize_resource :class => false
before_action :check_database_readable
+
+ def index
+ @notifications = UserNotifications.new(current_user)
+ end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index ceee49b55..15f7f9fa6 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -91,6 +91,8 @@ class User < ApplicationRecord
has_many :reports
+ has_many :notifications, :as => :recipient, :class_name => "Noticed::Notification"
+
has_many :social_links
accepts_nested_attributes_for :social_links, :allow_destroy => true
diff --git a/app/models/user_notifications.rb b/app/models/user_notifications.rb
new file mode 100644
index 000000000..b1ef8881e
--- /dev/null
+++ b/app/models/user_notifications.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+class UserNotifications
+ class Notification
+ def self.from(notification)
+ event_type_name = event_type_name_of(notification)
+ klass = "UserNotifications::#{event_type_name}Notification".constantize
+ klass.new(notification)
+ end
+
+ # Takes "ChangesetCommentNotifier::Notification", returns "ChangesetComment"
+ def self.event_type_name_of(notification)
+ notification.class.name.sub("Notifier::Notification", "")
+ end
+
+ def initialize(notification)
+ @notification = notification
+ end
+
+ delegate :record, :to => :@notification
+
+ def to_partial_path
+ event_type_name = self.class.event_type_name_of(@notification)
+ "notifications/#{event_type_name.underscore}"
+ end
+
+ def timestamp
+ record.created_at
+ end
+ end
+
+ include Enumerable
+
+ LISTABLE_NOTIFICATIONS = [].freeze
+
+ def initialize(user)
+ @user = user
+ end
+
+ def each(&)
+ @user
+ .notifications
+ .where(:type => LISTABLE_NOTIFICATIONS)
+ .newest_first
+ .map { |instance| Notification.from(instance) }
+ .each(&)
+ end
+
+ def empty?
+ none?
+ end
+end
diff --git a/app/views/notifications/index.html.erb b/app/views/notifications/index.html.erb
index 7de863324..1240a1b62 100644
--- a/app/views/notifications/index.html.erb
+++ b/app/views/notifications/index.html.erb
@@ -8,4 +8,13 @@
<% end %>
-<%= t(".no_notifications") %>
+<% if @notifications.empty? %>
+ <%= t(".no_notifications") %>
+<% else %>
+
+ <% @notifications.each do |notification| %>
+ <%= render :partial => notification.to_partial_path, :object => notification, :as => :notification %>
+
+ <% end %>
+
+<% end %>
diff --git a/test/factories/notifications.rb b/test/factories/notifications.rb
index cb582fccb..aa1d4d343 100644
--- a/test/factories/notifications.rb
+++ b/test/factories/notifications.rb
@@ -1,6 +1,37 @@
# frozen_string_literal: true
FactoryBot.define do
+ factory :notification, :class => "ApplicationNotifier::Notification" do
+ initialize_with do
+ notifier_class = self.notifier_class || "#{record.class.name}Notifier".constantize
+ notification_class = notifier_class::Notification
+ notification_class.new
+ end
+
+ recipient :factory => :user
+
+ event do
+ association :notifier, :record => record, :notifier_class => notifier_class, :params => notifier_params
+ end
+
+ transient do
+ record { nil }
+ notifier_class { nil }
+ notifier_params { nil }
+ end
+ end
+
+ factory :notifier, :class => "ApplicationNotifier" do
+ initialize_with do
+ notifier_class = self.notifier_class || "#{record.class.name}Notifier".constantize
+ notifier_class.new(:record => record)
+ end
+
+ transient do
+ notifier_class { nil }
+ end
+ end
+
factory :changeset_comment_notification, :class => "ChangesetCommentNotifier::Notification" do
event :factory => :changeset_comment_notifier
recipient :factory => :user
--
2.47.3