announcement.rb 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. # frozen_string_literal: true
  2. # == Schema Information
  3. #
  4. # Table name: announcements
  5. #
  6. # id :bigint(8) not null, primary key
  7. # text :text default(""), not null
  8. # published :boolean default(FALSE), not null
  9. # all_day :boolean default(FALSE), not null
  10. # scheduled_at :datetime
  11. # starts_at :datetime
  12. # ends_at :datetime
  13. # created_at :datetime not null
  14. # updated_at :datetime not null
  15. # published_at :datetime
  16. # status_ids :bigint(8) is an Array
  17. #
  18. class Announcement < ApplicationRecord
  19. scope :unpublished, -> { where(published: false) }
  20. scope :published, -> { where(published: true) }
  21. scope :chronological, -> { order(coalesced_chronology_timestamps.asc) }
  22. scope :reverse_chronological, -> { order(coalesced_chronology_timestamps.desc) }
  23. has_many :announcement_mutes, dependent: :destroy
  24. has_many :announcement_reactions, dependent: :destroy
  25. validates :text, presence: true
  26. validates :starts_at, presence: true, if: :ends_at?
  27. validates :ends_at, presence: true, if: :starts_at?
  28. before_validation :set_published, on: :create
  29. class << self
  30. def coalesced_chronology_timestamps
  31. Arel.sql(
  32. <<~SQL.squish
  33. COALESCE(announcements.starts_at, announcements.scheduled_at, announcements.published_at, announcements.created_at)
  34. SQL
  35. )
  36. end
  37. end
  38. def to_log_human_identifier
  39. text
  40. end
  41. def publish!
  42. update!(published: true, published_at: Time.now.utc, scheduled_at: nil)
  43. end
  44. def unpublish!
  45. update!(published: false, scheduled_at: nil)
  46. end
  47. def mentions
  48. @mentions ||= Account.from_text(text)
  49. end
  50. def statuses
  51. @statuses ||= begin
  52. if status_ids.nil?
  53. []
  54. else
  55. Status.with_includes.distributable_visibility.where(id: status_ids)
  56. end
  57. end
  58. end
  59. def tags
  60. @tags ||= Tag.find_or_create_by_names(Extractor.extract_hashtags(text))
  61. end
  62. def emojis
  63. @emojis ||= CustomEmoji.from_text(text)
  64. end
  65. def reactions(account = nil)
  66. grouped_ordered_announcement_reactions.select(
  67. [:name, :custom_emoji_id, 'COUNT(*) as count'].tap do |values|
  68. values << value_for_reaction_me_column(account)
  69. end
  70. ).to_a.tap do |records|
  71. ActiveRecord::Associations::Preloader.new(records: records, associations: :custom_emoji).call
  72. end
  73. end
  74. private
  75. def grouped_ordered_announcement_reactions
  76. announcement_reactions
  77. .group(:announcement_id, :name, :custom_emoji_id)
  78. .order(
  79. Arel.sql('MIN(created_at)').asc
  80. )
  81. end
  82. def value_for_reaction_me_column(account)
  83. if account.nil?
  84. 'FALSE AS me'
  85. else
  86. <<~SQL.squish
  87. EXISTS(
  88. SELECT 1
  89. FROM announcement_reactions inner_reactions
  90. WHERE inner_reactions.account_id = #{account.id}
  91. AND inner_reactions.announcement_id = announcement_reactions.announcement_id
  92. AND inner_reactions.name = announcement_reactions.name
  93. ) AS me
  94. SQL
  95. end
  96. end
  97. def set_published
  98. return unless scheduled_at.blank? || scheduled_at.past?
  99. self.published = true
  100. self.published_at = Time.now.utc
  101. end
  102. end