Rename :poll to :preloadable_poll and :owned_poll to :poll on Status (#10401)
Also, fix some n+1 queries Resolve #10365
This commit is contained in:
		@@ -105,8 +105,8 @@ module StreamEntriesHelper
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def poll_summary(status)
 | 
			
		||||
    return unless status.poll
 | 
			
		||||
    status.poll.options.map { |o| "[ ] #{o}" }.join("\n")
 | 
			
		||||
    return unless status.preloadable_poll
 | 
			
		||||
    status.preloadable_poll.options.map { |o| "[ ] #{o}" }.join("\n")
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def status_description(status)
 | 
			
		||||
 
 | 
			
		||||
@@ -68,7 +68,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
 | 
			
		||||
        thread: replied_to_status,
 | 
			
		||||
        conversation: conversation_from_uri(@object['conversation']),
 | 
			
		||||
        media_attachment_ids: process_attachments.take(4).map(&:id),
 | 
			
		||||
        owned_poll: process_poll,
 | 
			
		||||
        poll: process_poll,
 | 
			
		||||
      }
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
@@ -240,11 +240,11 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def poll_vote?
 | 
			
		||||
    return false if replied_to_status.nil? || replied_to_status.poll.nil? || !replied_to_status.local? || !replied_to_status.poll.options.include?(@object['name'])
 | 
			
		||||
    return false if replied_to_status.nil? || replied_to_status.preloadable_poll.nil? || !replied_to_status.local? || !replied_to_status.preloadable_poll.options.include?(@object['name'])
 | 
			
		||||
 | 
			
		||||
    unless replied_to_status.poll.expired?
 | 
			
		||||
      replied_to_status.poll.votes.create!(account: @account, choice: replied_to_status.poll.options.index(@object['name']), uri: @object['id'])
 | 
			
		||||
      ActivityPub::DistributePollUpdateWorker.perform_in(3.minutes, replied_to_status.id) unless replied_to_status.poll.hide_totals?
 | 
			
		||||
    unless replied_to_status.preloadable_poll.expired?
 | 
			
		||||
      replied_to_status.preloadable_poll.votes.create!(account: @account, choice: replied_to_status.preloadable_poll.options.index(@object['name']), uri: @object['id'])
 | 
			
		||||
      ActivityPub::DistributePollUpdateWorker.perform_in(3.minutes, replied_to_status.id) unless replied_to_status.preloadable_poll.hide_totals?
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    true
 | 
			
		||||
 
 | 
			
		||||
@@ -23,8 +23,8 @@ class ActivityPub::Activity::Update < ActivityPub::Activity
 | 
			
		||||
    return reject_payload! if invalid_origin?(@object['id'])
 | 
			
		||||
 | 
			
		||||
    status = Status.find_by(uri: object_uri, account_id: @account.id)
 | 
			
		||||
    return if status.nil? || status.poll.nil?
 | 
			
		||||
    return if status.nil? || status.preloadable_poll.nil?
 | 
			
		||||
 | 
			
		||||
    ActivityPub::ProcessPollService.new.call(status.poll, @object)
 | 
			
		||||
    ActivityPub::ProcessPollService.new.call(status.preloadable_poll, @object)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -19,8 +19,8 @@ class Formatter
 | 
			
		||||
 | 
			
		||||
    raw_content = status.text
 | 
			
		||||
 | 
			
		||||
    if options[:inline_poll_options] && status.poll
 | 
			
		||||
      raw_content = raw_content + "\n\n" + status.poll.options.map { |title| "[ ] #{title}" }.join("\n")
 | 
			
		||||
    if options[:inline_poll_options] && status.preloadable_poll
 | 
			
		||||
      raw_content = raw_content + "\n\n" + status.preloadable_poll.options.map { |title| "[ ] #{title}" }.join("\n")
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    return '' if raw_content.blank?
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ class Notification < ApplicationRecord
 | 
			
		||||
    poll:           'Poll',
 | 
			
		||||
  }.freeze
 | 
			
		||||
 | 
			
		||||
  STATUS_INCLUDES = [:account, :application, :media_attachments, :tags, active_mentions: :account, reblog: [:account, :application, :media_attachments, :tags, active_mentions: :account]].freeze
 | 
			
		||||
  STATUS_INCLUDES = [:account, :application, :preloadable_poll, :media_attachments, :tags, active_mentions: :account, reblog: [:account, :application, :preloadable_poll, :media_attachments, :tags, active_mentions: :account]].freeze
 | 
			
		||||
 | 
			
		||||
  belongs_to :account, optional: true
 | 
			
		||||
  belongs_to :from_account, class_name: 'Account', optional: true
 | 
			
		||||
 
 | 
			
		||||
@@ -45,7 +45,7 @@ class Status < ApplicationRecord
 | 
			
		||||
  belongs_to :account, inverse_of: :statuses
 | 
			
		||||
  belongs_to :in_reply_to_account, foreign_key: 'in_reply_to_account_id', class_name: 'Account', optional: true
 | 
			
		||||
  belongs_to :conversation, optional: true
 | 
			
		||||
  belongs_to :poll, optional: true
 | 
			
		||||
  belongs_to :preloadable_poll, class_name: 'Poll', foreign_key: 'poll_id', optional: true
 | 
			
		||||
 | 
			
		||||
  belongs_to :thread, foreign_key: 'in_reply_to_id', class_name: 'Status', inverse_of: :replies, optional: true
 | 
			
		||||
  belongs_to :reblog, foreign_key: 'reblog_of_id', class_name: 'Status', inverse_of: :reblogs, optional: true
 | 
			
		||||
@@ -63,7 +63,7 @@ class Status < ApplicationRecord
 | 
			
		||||
  has_one :notification, as: :activity, dependent: :destroy
 | 
			
		||||
  has_one :stream_entry, as: :activity, inverse_of: :status
 | 
			
		||||
  has_one :status_stat, inverse_of: :status
 | 
			
		||||
  has_one :owned_poll, class_name: 'Poll', inverse_of: :status, dependent: :destroy
 | 
			
		||||
  has_one :poll, inverse_of: :status, dependent: :destroy
 | 
			
		||||
 | 
			
		||||
  validates :uri, uniqueness: true, presence: true, unless: :local?
 | 
			
		||||
  validates :text, presence: true, unless: -> { with_media? || reblog? }
 | 
			
		||||
@@ -72,7 +72,7 @@ class Status < ApplicationRecord
 | 
			
		||||
  validates :reblog, uniqueness: { scope: :account }, if: :reblog?
 | 
			
		||||
  validates :visibility, exclusion: { in: %w(direct limited) }, if: :reblog?
 | 
			
		||||
 | 
			
		||||
  accepts_nested_attributes_for :owned_poll
 | 
			
		||||
  accepts_nested_attributes_for :poll
 | 
			
		||||
 | 
			
		||||
  default_scope { recent }
 | 
			
		||||
 | 
			
		||||
@@ -107,7 +107,7 @@ class Status < ApplicationRecord
 | 
			
		||||
                   :tags,
 | 
			
		||||
                   :preview_cards,
 | 
			
		||||
                   :stream_entry,
 | 
			
		||||
                   :poll,
 | 
			
		||||
                   :preloadable_poll,
 | 
			
		||||
                   account: :account_stat,
 | 
			
		||||
                   active_mentions: { account: :account_stat },
 | 
			
		||||
                   reblog: [
 | 
			
		||||
@@ -118,7 +118,7 @@ class Status < ApplicationRecord
 | 
			
		||||
                     :media_attachments,
 | 
			
		||||
                     :conversation,
 | 
			
		||||
                     :status_stat,
 | 
			
		||||
                     :poll,
 | 
			
		||||
                     :preloadable_poll,
 | 
			
		||||
                     account: :account_stat,
 | 
			
		||||
                     active_mentions: { account: :account_stat },
 | 
			
		||||
                   ],
 | 
			
		||||
@@ -214,10 +214,11 @@ class Status < ApplicationRecord
 | 
			
		||||
 | 
			
		||||
  def emojis
 | 
			
		||||
    return @emojis if defined?(@emojis)
 | 
			
		||||
    fields = [spoiler_text, text]
 | 
			
		||||
    fields += owned_poll.options unless owned_poll.nil?
 | 
			
		||||
 | 
			
		||||
    fields  = [spoiler_text, text]
 | 
			
		||||
    fields += preloadable_poll.options unless preloadable_poll.nil?
 | 
			
		||||
 | 
			
		||||
    @emojis = CustomEmoji.from_text(fields.join(' '), account.domain)
 | 
			
		||||
    @emojis
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def mark_for_mass_destruction!
 | 
			
		||||
@@ -453,7 +454,7 @@ class Status < ApplicationRecord
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def set_poll_id
 | 
			
		||||
    update_column(:poll_id, owned_poll.id) unless owned_poll.nil?
 | 
			
		||||
    update_column(:poll_id, poll.id) unless poll.nil?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def set_visibility
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@ class ActivityPub::NoteSerializer < ActivityPub::Serializer
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def type
 | 
			
		||||
    object.poll ? 'Question' : 'Note'
 | 
			
		||||
    object.preloadable_poll ? 'Question' : 'Note'
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def summary
 | 
			
		||||
@@ -125,29 +125,29 @@ class ActivityPub::NoteSerializer < ActivityPub::Serializer
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def poll_options
 | 
			
		||||
    object.poll.loaded_options
 | 
			
		||||
    object.preloadable_poll.loaded_options
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def poll_and_multiple?
 | 
			
		||||
    object.poll&.multiple?
 | 
			
		||||
    object.preloadable_poll&.multiple?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def poll_and_not_multiple?
 | 
			
		||||
    object.poll && !object.poll.multiple?
 | 
			
		||||
    object.preloadable_poll && !object.preloadable_poll.multiple?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def closed
 | 
			
		||||
    object.poll.expires_at.iso8601
 | 
			
		||||
    object.preloadable_poll.expires_at.iso8601
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  alias end_time closed
 | 
			
		||||
 | 
			
		||||
  def poll_and_expires?
 | 
			
		||||
    object.poll&.expires_at&.present?
 | 
			
		||||
    object.preloadable_poll&.expires_at&.present?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def poll_and_expired?
 | 
			
		||||
    object.poll&.expired?
 | 
			
		||||
    object.preloadable_poll&.expired?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class MediaAttachmentSerializer < ActivityPub::Serializer
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@ class ActivityPub::UpdatePollSerializer < ActivityPub::Serializer
 | 
			
		||||
  has_one :object, serializer: ActivityPub::NoteSerializer
 | 
			
		||||
 | 
			
		||||
  def id
 | 
			
		||||
    [ActivityPub::TagManager.instance.uri_for(object), '#updates/', object.poll.updated_at.to_i].join
 | 
			
		||||
    [ActivityPub::TagManager.instance.uri_for(object), '#updates/', object.preloadable_poll.updated_at.to_i].join
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def type
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@ class REST::StatusSerializer < ActiveModel::Serializer
 | 
			
		||||
  has_many :emojis, serializer: REST::CustomEmojiSerializer
 | 
			
		||||
 | 
			
		||||
  has_one :preview_card, key: :card, serializer: REST::PreviewCardSerializer
 | 
			
		||||
  has_one :poll, serializer: REST::PollSerializer
 | 
			
		||||
  has_one :preloadable_poll, key: :poll, serializer: REST::PollSerializer
 | 
			
		||||
 | 
			
		||||
  def id
 | 
			
		||||
    object.id.to_s
 | 
			
		||||
 
 | 
			
		||||
@@ -155,7 +155,7 @@ class PostStatusService < BaseService
 | 
			
		||||
      text: @text,
 | 
			
		||||
      media_attachments: @media || [],
 | 
			
		||||
      thread: @in_reply_to,
 | 
			
		||||
      owned_poll_attributes: poll_attributes,
 | 
			
		||||
      poll_attributes: poll_attributes,
 | 
			
		||||
      sensitive: (@options[:sensitive].nil? ? @account.user&.setting_default_sensitive : @options[:sensitive]) || @options[:spoiler_text].present?,
 | 
			
		||||
      spoiler_text: @options[:spoiler_text] || '',
 | 
			
		||||
      visibility: @visibility,
 | 
			
		||||
 
 | 
			
		||||
@@ -22,9 +22,9 @@
 | 
			
		||||
        %a.status__content__spoiler-link{ href: '#' }= t('statuses.show_more')
 | 
			
		||||
    .e-content{ lang: status.language, style: "display: #{!current_account&.user&.setting_expand_spoilers && status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }= Formatter.instance.format(status, custom_emojify: true, autoplay: autoplay)
 | 
			
		||||
 | 
			
		||||
  - if status.poll
 | 
			
		||||
    = react_component :poll, disabled: true, poll: ActiveModelSerializers::SerializableResource.new(status.poll, serializer: REST::PollSerializer, scope: current_user, scope_name: :current_user).as_json do
 | 
			
		||||
      = render partial: 'stream_entries/poll', locals: { status: status, poll: status.poll, autoplay: autoplay }
 | 
			
		||||
  - if status.preloadable_poll
 | 
			
		||||
    = react_component :poll, disabled: true, poll: ActiveModelSerializers::SerializableResource.new(status.preloadable_poll, serializer: REST::PollSerializer, scope: current_user, scope_name: :current_user).as_json do
 | 
			
		||||
      = render partial: 'stream_entries/poll', locals: { status: status, poll: status.preloadable_poll, autoplay: autoplay }
 | 
			
		||||
  - elsif !status.media_attachments.empty?
 | 
			
		||||
    - if status.media_attachments.first.video?
 | 
			
		||||
      - video = status.media_attachments.first
 | 
			
		||||
 
 | 
			
		||||
@@ -26,9 +26,9 @@
 | 
			
		||||
        %a.status__content__spoiler-link{ href: '#' }= t('statuses.show_more')
 | 
			
		||||
    .e-content{ lang: status.language, style: "display: #{!current_account&.user&.setting_expand_spoilers && status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }= Formatter.instance.format(status, custom_emojify: true, autoplay: autoplay)
 | 
			
		||||
 | 
			
		||||
  - if status.poll
 | 
			
		||||
    = react_component :poll, disabled: true, poll: ActiveModelSerializers::SerializableResource.new(status.poll, serializer: REST::PollSerializer, scope: current_user, scope_name: :current_user).as_json do
 | 
			
		||||
      = render partial: 'stream_entries/poll', locals: { status: status, poll: status.poll, autoplay: autoplay }
 | 
			
		||||
  - if status.preloadable_poll
 | 
			
		||||
    = react_component :poll, disabled: true, poll: ActiveModelSerializers::SerializableResource.new(status.preloadable_poll, serializer: REST::PollSerializer, scope: current_user, scope_name: :current_user).as_json do
 | 
			
		||||
      = render partial: 'stream_entries/poll', locals: { status: status, poll: status.preloadable_poll, autoplay: autoplay }
 | 
			
		||||
  - elsif !status.media_attachments.empty?
 | 
			
		||||
    - if status.media_attachments.first.video?
 | 
			
		||||
      - video = status.media_attachments.first
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@ class ActivityPub::DistributePollUpdateWorker
 | 
			
		||||
    @status  = Status.find(status_id)
 | 
			
		||||
    @account = @status.account
 | 
			
		||||
 | 
			
		||||
    return unless @status.poll
 | 
			
		||||
    return unless @status.preloadable_poll
 | 
			
		||||
 | 
			
		||||
    ActivityPub::DeliveryWorker.push_bulk(inboxes) do |inbox_url|
 | 
			
		||||
      [payload, @account.id, inbox_url]
 | 
			
		||||
@@ -29,7 +29,7 @@ class ActivityPub::DistributePollUpdateWorker
 | 
			
		||||
  def inboxes
 | 
			
		||||
    return @inboxes if defined?(@inboxes)
 | 
			
		||||
 | 
			
		||||
    @inboxes = [@status.mentions, @status.reblogs, @status.poll.votes].flat_map do |relation|
 | 
			
		||||
    @inboxes = [@status.mentions, @status.reblogs, @status.preloadable_poll.votes].flat_map do |relation|
 | 
			
		||||
      relation.includes(:account).map do |record|
 | 
			
		||||
        record.account.preferred_inbox_url if !record.account.local? && record.account.activitypub?
 | 
			
		||||
      end
 | 
			
		||||
 
 | 
			
		||||
@@ -2,8 +2,9 @@
 | 
			
		||||
en:
 | 
			
		||||
  activerecord:
 | 
			
		||||
    attributes:
 | 
			
		||||
      status:
 | 
			
		||||
        owned_poll: Poll
 | 
			
		||||
      poll:
 | 
			
		||||
        expires_at: Deadline
 | 
			
		||||
        options: Choices
 | 
			
		||||
    errors:
 | 
			
		||||
      models:
 | 
			
		||||
        account:
 | 
			
		||||
 
 | 
			
		||||
@@ -464,7 +464,7 @@ RSpec.describe ActivityPub::Activity::Create do
 | 
			
		||||
 | 
			
		||||
      context 'when a vote to a local poll' do
 | 
			
		||||
        let(:poll) { Fabricate(:poll, options: %w(Yellow Blue)) }
 | 
			
		||||
        let!(:local_status) { Fabricate(:status, owned_poll: poll) }
 | 
			
		||||
        let!(:local_status) { Fabricate(:status, poll: poll) }
 | 
			
		||||
 | 
			
		||||
        let(:object_json) do
 | 
			
		||||
          {
 | 
			
		||||
@@ -489,7 +489,7 @@ RSpec.describe ActivityPub::Activity::Create do
 | 
			
		||||
          poll.save(validate: false)
 | 
			
		||||
          poll
 | 
			
		||||
        end
 | 
			
		||||
        let!(:local_status) { Fabricate(:status, owned_poll: poll) }
 | 
			
		||||
        let!(:local_status) { Fabricate(:status, poll: poll) }
 | 
			
		||||
 | 
			
		||||
        let(:object_json) do
 | 
			
		||||
          {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user