Class: Notification
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- Notification
- Defined in:
- app/models/notification.rb
Constant Summary collapse
- MEMBERSHIP_REQUEST_CONSOLIDATION_WINDOW_HOURS =
24
Instance Attribute Summary collapse
-
#skip_send_email ⇒ Object
Returns the value of attribute skip_send_email.
Class Method Summary collapse
- .consolidate_or_create!(notification_params) ⇒ Object
- .ensure_consistency! ⇒ Object
- .high_priority_types ⇒ Object
- .interesting_after(min_date) ⇒ Object
- .like_types ⇒ Object
- .mark_posts_read(user, topic_id, post_numbers) ⇒ Object
- .normal_priority_types ⇒ Object
- .prioritized_list(user, count: 30, types: []) ⇒ Object
- .purge_old! ⇒ Object
- .read(user, notification_ids) ⇒ Object
- .read_types(user, types = nil) ⇒ Object
- .recent_report(user, count = nil, types = []) ⇒ Object
-
.remove_for(user_id, topic_id) ⇒ Object
Clean up any notifications the user can no longer see.
- .types ⇒ Object
Instance Method Summary collapse
-
#data_hash ⇒ Object
Be wary of calling this frequently.
- #post ⇒ Object
- #post_id ⇒ Object
- #unread_high_priority? ⇒ Boolean
- #url ⇒ Object
Instance Attribute Details
#skip_send_email ⇒ Object
Returns the value of attribute skip_send_email.
55 56 57 |
# File 'app/models/notification.rb', line 55 def skip_send_email @skip_send_email end |
Class Method Details
.consolidate_or_create!(notification_params) ⇒ Object
69 70 71 72 73 74 75 76 |
# File 'app/models/notification.rb', line 69 def self.consolidate_or_create!(notification_params) notification = new(notification_params) consolidation_planner = Notifications::ConsolidationPlanner.new consolidated_notification = consolidation_planner.consolidate_or_save!(notification) consolidated_notification == :no_plan ? notification.tap(&:save!) : consolidated_notification end |
.ensure_consistency! ⇒ Object
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'app/models/notification.rb', line 97 def self.ensure_consistency! DB.exec(<<~SQL) DELETE FROM notifications n WHERE high_priority AND n.topic_id IS NOT NULL AND NOT EXISTS ( SELECT 1 FROM posts p JOIN topics t ON t.id = p.topic_id WHERE p.deleted_at IS NULL AND t.deleted_at IS NULL AND p.post_number = n.post_number AND t.id = n.topic_id ) SQL end |
.high_priority_types ⇒ Object
163 164 165 |
# File 'app/models/notification.rb', line 163 def self.high_priority_types @high_priority_types ||= [types[:private_message], types[:bookmark_reminder]] end |
.interesting_after(min_date) ⇒ Object
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'app/models/notification.rb', line 190 def self.interesting_after(min_date) result = where("created_at > ?", min_date) .includes(:topic) .visible .unread .limit(20) .order( "CASE WHEN notification_type = #{Notification.types[:replied]} THEN 1 WHEN notification_type = #{Notification.types[:mentioned]} THEN 2 ELSE 3 END, created_at DESC", ) .to_a # Remove any duplicates by type and topic if result.present? seen = {} to_remove = Set.new result.each do |r| seen[r.notification_type] ||= Set.new if seen[r.notification_type].include?(r.topic_id) to_remove << r.id else seen[r.notification_type] << r.topic_id end end result.reject! { |r| to_remove.include?(r.id) } end result end |
.like_types ⇒ Object
252 253 254 255 256 257 258 |
# File 'app/models/notification.rb', line 252 def self.like_types [ Notification.types[:liked], Notification.types[:liked_consolidated], Notification.types[:reaction], ] end |
.mark_posts_read(user, topic_id, post_numbers) ⇒ Object
171 172 173 174 175 176 177 178 |
# File 'app/models/notification.rb', line 171 def self.mark_posts_read(user, topic_id, post_numbers) Notification.where( user_id: user.id, topic_id: topic_id, post_number: post_numbers, read: false, ).update_all(read: true) end |
.normal_priority_types ⇒ Object
167 168 169 |
# File 'app/models/notification.rb', line 167 def self.normal_priority_types @normal_priority_types ||= types.reject { |_k, v| high_priority_types.include?(v) }.values end |
.prioritized_list(user, count: 30, types: []) ⇒ Object
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
# File 'app/models/notification.rb', line 260 def self.prioritized_list(user, count: 30, types: []) return [] if !user&.user_option notifications = user .notifications .includes(:topic) .visible .prioritized(types.present? ? [] : like_types) .limit(count) if types.present? notifications = notifications.where(notification_type: types) elsif user.user_option.like_notification_frequency == UserOption.like_notification_frequency_type[:never] like_types.each do |notification_type| notifications = notifications.where("notification_type <> ?", notification_type) end end notifications.to_a end |
.purge_old! ⇒ Object
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'app/models/notification.rb', line 78 def self.purge_old! return if SiteSetting.max_notifications_per_user == 0 DB.exec(<<~SQL, SiteSetting.max_notifications_per_user) DELETE FROM notifications n1 USING ( SELECT * FROM ( SELECT user_id, id, rank() OVER (PARTITION BY user_id ORDER BY id DESC) FROM notifications ) AS X WHERE rank = ? ) n2 WHERE n1.user_id = n2.user_id AND n1.id < n2.id SQL end |
.read(user, notification_ids) ⇒ Object
180 181 182 |
# File 'app/models/notification.rb', line 180 def self.read(user, notification_ids) Notification.where(id: notification_ids, user_id: user.id, read: false).update_all(read: true) end |
.read_types(user, types = nil) ⇒ Object
184 185 186 187 188 |
# File 'app/models/notification.rb', line 184 def self.read_types(user, types = nil) query = Notification.where(user_id: user.id, read: false) query = query.where(notification_type: types) if types query.update_all(read: true) end |
.recent_report(user, count = nil, types = []) ⇒ Object
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 |
# File 'app/models/notification.rb', line 282 def self.recent_report(user, count = nil, types = []) return unless user && user.user_option count ||= 10 notifications = user.notifications.visible.recent(count).includes(:topic) notifications = notifications.where(notification_type: types) if types.present? if user.user_option.like_notification_frequency == UserOption.like_notification_frequency_type[:never] [ Notification.types[:liked], Notification.types[:liked_consolidated], ].each do |notification_type| notifications = notifications.where("notification_type <> ?", notification_type) end end notifications = notifications.to_a if notifications.present? builder = DB.build(<<~SQL) SELECT n.id FROM notifications n /*where*/ ORDER BY n.id ASC /*limit*/ SQL builder.where(<<~SQL, user_id: user.id) n.high_priority = TRUE AND n.user_id = :user_id AND NOT read SQL builder.where("notification_type IN (:types)", types: types) if types.present? builder.limit(count.to_i) ids = builder.query_single if ids.length > 0 notifications += user .notifications .order("notifications.created_at DESC") .where(id: ids) .joins(:topic) .limit(count) end notifications .uniq(&:id) .sort do |x, y| if x.unread_high_priority? && !y.unread_high_priority? -1 elsif y.unread_high_priority? && !x.unread_high_priority? 1 else y.created_at <=> x.created_at end end .take(count) else [] end end |
.remove_for(user_id, topic_id) ⇒ Object
Clean up any notifications the user can no longer see. For example, if a topic was previously public then turns private.
226 227 228 |
# File 'app/models/notification.rb', line 226 def self.remove_for(user_id, topic_id) Notification.where(user_id: user_id, topic_id: topic_id).delete_all end |
.types ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'app/models/notification.rb', line 115 def self.types @types ||= Enum.new( mentioned: 1, replied: 2, quoted: 3, edited: 4, liked: 5, private_message: 6, invited_to_private_message: 7, invitee_accepted: 8, posted: 9, moved_post: 10, linked: 11, granted_badge: 12, invited_to_topic: 13, custom: 14, group_mentioned: 15, group_message_summary: 16, watching_first_post: 17, topic_reminder: 18, liked_consolidated: 19, post_approved: 20, code_review_commit_approved: 21, membership_request_accepted: 22, membership_request_consolidated: 23, bookmark_reminder: 24, reaction: 25, votes_released: 26, event_reminder: 27, event_invitation: 28, chat_mention: 29, chat_message: 30, chat_invitation: 31, chat_group_mention: 32, # March 2022 - This is obsolete, as all chat_mentions use `chat_mention` type chat_quoted: 33, assigned: 34, question_answer_user_commented: 35, # Used by https://github.com/discourse/discourse-question-answer watching_category_or_tag: 36, new_features: 37, admin_problems: 38, following: 800, # Used by https://github.com/discourse/discourse-follow following_created_topic: 801, # Used by https://github.com/discourse/discourse-follow following_replied: 802, # Used by https://github.com/discourse/discourse-follow circles_activity: 900, # Used by https://github.com/discourse/discourse-circles ) end |
Instance Method Details
#data_hash ⇒ Object
Be wary of calling this frequently. O(n) JSON parsing can suck.
231 232 233 234 235 236 237 238 239 240 241 |
# File 'app/models/notification.rb', line 231 def data_hash @data_hash ||= begin return {} if data.blank? parsed = JSON.parse(data) return {} if parsed.blank? parsed.with_indifferent_access end end |
#post ⇒ Object
247 248 249 250 |
# File 'app/models/notification.rb', line 247 def post return if topic_id.blank? || post_number.blank? Post.find_by(topic_id: topic_id, post_number: post_number) end |
#post_id ⇒ Object
350 351 352 |
# File 'app/models/notification.rb', line 350 def post_id Post.where(topic: topic_id, post_number: post_number).pick(:id) end |
#unread_high_priority? ⇒ Boolean
346 347 348 |
# File 'app/models/notification.rb', line 346 def unread_high_priority? self.high_priority? && !read end |
#url ⇒ Object
243 244 245 |
# File 'app/models/notification.rb', line 243 def url topic.relative_url(post_number) if topic.present? end |