notification.rb 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. # frozen_string_literal: true
  2. # == Schema Information
  3. #
  4. # Table name: notifications
  5. #
  6. # id :bigint(8) not null, primary key
  7. # activity_id :bigint(8) not null
  8. # activity_type :string not null
  9. # created_at :datetime not null
  10. # updated_at :datetime not null
  11. # account_id :bigint(8) not null
  12. # from_account_id :bigint(8) not null
  13. # type :string
  14. #
  15. class Notification < ApplicationRecord
  16. self.inheritance_column = nil
  17. include Paginable
  18. include Cacheable
  19. LEGACY_TYPE_CLASS_MAP = {
  20. 'Mention' => :mention,
  21. 'Status' => :reblog,
  22. 'Follow' => :follow,
  23. 'FollowRequest' => :follow_request,
  24. 'Favourite' => :favourite,
  25. 'Poll' => :poll,
  26. }.freeze
  27. TYPES = %i(
  28. mention
  29. status
  30. reblog
  31. follow
  32. follow_request
  33. favourite
  34. poll
  35. ).freeze
  36. STATUS_INCLUDES = [:account, :application, :preloadable_poll, :media_attachments, :tags, active_mentions: :account, reblog: [:account, :application, :preloadable_poll, :media_attachments, :tags, active_mentions: :account]].freeze
  37. belongs_to :account, optional: true
  38. belongs_to :from_account, class_name: 'Account', optional: true
  39. belongs_to :activity, polymorphic: true, optional: true
  40. belongs_to :mention, foreign_type: 'Mention', foreign_key: 'activity_id', optional: true
  41. belongs_to :status, foreign_type: 'Status', foreign_key: 'activity_id', optional: true
  42. belongs_to :follow, foreign_type: 'Follow', foreign_key: 'activity_id', optional: true
  43. belongs_to :follow_request, foreign_type: 'FollowRequest', foreign_key: 'activity_id', optional: true
  44. belongs_to :favourite, foreign_type: 'Favourite', foreign_key: 'activity_id', optional: true
  45. belongs_to :poll, foreign_type: 'Poll', foreign_key: 'activity_id', optional: true
  46. validates :type, inclusion: { in: TYPES }
  47. scope :without_suspended, -> { joins(:from_account).merge(Account.without_suspended) }
  48. scope :browserable, ->(exclude_types = [], account_id = nil) {
  49. types = TYPES - exclude_types.map(&:to_sym)
  50. if account_id.nil?
  51. where(type: types)
  52. else
  53. where(type: types, from_account_id: account_id)
  54. end
  55. }
  56. cache_associated :from_account, status: STATUS_INCLUDES, mention: [status: STATUS_INCLUDES], favourite: [:account, status: STATUS_INCLUDES], follow: :account, follow_request: :account, poll: [status: STATUS_INCLUDES]
  57. def type
  58. @type ||= (super || LEGACY_TYPE_CLASS_MAP[activity_type]).to_sym
  59. end
  60. def target_status
  61. case type
  62. when :status
  63. status
  64. when :reblog
  65. status&.reblog
  66. when :favourite
  67. favourite&.status
  68. when :mention
  69. mention&.status
  70. when :poll
  71. poll&.status
  72. end
  73. end
  74. class << self
  75. def cache_ids
  76. select(:id, :updated_at, :activity_type, :activity_id)
  77. end
  78. def reload_stale_associations!(cached_items)
  79. account_ids = (cached_items.map(&:from_account_id) + cached_items.map { |item| item.target_status&.account_id }.compact).uniq
  80. return if account_ids.empty?
  81. accounts = Account.where(id: account_ids).includes(:account_stat).each_with_object({}) { |a, h| h[a.id] = a }
  82. cached_items.each do |item|
  83. item.from_account = accounts[item.from_account_id]
  84. item.target_status.account = accounts[item.target_status.account_id] if item.target_status
  85. end
  86. end
  87. end
  88. after_initialize :set_from_account
  89. before_validation :set_from_account
  90. private
  91. def set_from_account
  92. return unless new_record?
  93. case activity_type
  94. when 'Status', 'Follow', 'Favourite', 'FollowRequest', 'Poll'
  95. self.from_account_id = activity&.account_id
  96. when 'Mention'
  97. self.from_account_id = activity&.status&.account_id
  98. end
  99. end
  100. end