Before this patch, if remote poll options have leading or trailing spaces, the information stored locally won't match them, causing federated voting to fail.
		
			
				
	
	
		
			114 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			114 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
| # frozen_string_literal: true
 | |
| # == Schema Information
 | |
| #
 | |
| # Table name: polls
 | |
| #
 | |
| #  id              :bigint(8)        not null, primary key
 | |
| #  account_id      :bigint(8)
 | |
| #  status_id       :bigint(8)
 | |
| #  expires_at      :datetime
 | |
| #  options         :string           default([]), not null, is an Array
 | |
| #  cached_tallies  :bigint(8)        default([]), not null, is an Array
 | |
| #  multiple        :boolean          default(FALSE), not null
 | |
| #  hide_totals     :boolean          default(FALSE), not null
 | |
| #  votes_count     :bigint(8)        default(0), not null
 | |
| #  last_fetched_at :datetime
 | |
| #  created_at      :datetime         not null
 | |
| #  updated_at      :datetime         not null
 | |
| #  lock_version    :integer          default(0), not null
 | |
| #  voters_count    :bigint(8)
 | |
| #
 | |
| 
 | |
| class Poll < ApplicationRecord
 | |
|   include Expireable
 | |
| 
 | |
|   belongs_to :account
 | |
|   belongs_to :status
 | |
| 
 | |
|   has_many :votes, class_name: 'PollVote', inverse_of: :poll, dependent: :destroy
 | |
| 
 | |
|   has_many :notifications, as: :activity, dependent: :destroy
 | |
| 
 | |
|   validates :options, presence: true
 | |
|   validates :expires_at, presence: true, if: :local?
 | |
|   validates_with PollValidator, on: :create, if: :local?
 | |
| 
 | |
|   scope :attached, -> { where.not(status_id: nil) }
 | |
|   scope :unattached, -> { where(status_id: nil) }
 | |
| 
 | |
|   before_validation :prepare_options, if: :local?
 | |
|   before_validation :prepare_votes_count
 | |
| 
 | |
|   after_initialize :prepare_cached_tallies
 | |
| 
 | |
|   after_commit :reset_parent_cache, on: :update
 | |
| 
 | |
|   def loaded_options
 | |
|     options.map.with_index { |title, key| Option.new(self, key.to_s, title, show_totals_now? ? cached_tallies[key] : nil) }
 | |
|   end
 | |
| 
 | |
|   def possibly_stale?
 | |
|     remote? && last_fetched_before_expiration? && time_passed_since_last_fetch?
 | |
|   end
 | |
| 
 | |
|   def voted?(account)
 | |
|     account.id == account_id || votes.where(account: account).exists?
 | |
|   end
 | |
| 
 | |
|   def own_votes(account)
 | |
|     votes.where(account: account).pluck(:choice)
 | |
|   end
 | |
| 
 | |
|   delegate :local?, to: :account
 | |
| 
 | |
|   def remote?
 | |
|     !local?
 | |
|   end
 | |
| 
 | |
|   def emojis
 | |
|     @emojis ||= CustomEmoji.from_text(options.join(' '), account.domain)
 | |
|   end
 | |
| 
 | |
|   class Option < ActiveModelSerializers::Model
 | |
|     attributes :id, :title, :votes_count, :poll
 | |
| 
 | |
|     def initialize(poll, id, title, votes_count)
 | |
|       @poll        = poll
 | |
|       @id          = id
 | |
|       @title       = title
 | |
|       @votes_count = votes_count
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   private
 | |
| 
 | |
|   def prepare_cached_tallies
 | |
|     self.cached_tallies = options.map { 0 } if cached_tallies.empty?
 | |
|   end
 | |
| 
 | |
|   def prepare_votes_count
 | |
|     self.votes_count = cached_tallies.sum unless cached_tallies.empty?
 | |
|   end
 | |
| 
 | |
|   def prepare_options
 | |
|     self.options = options.map(&:strip).reject(&:blank?)
 | |
|   end
 | |
| 
 | |
|   def reset_parent_cache
 | |
|     return if status_id.nil?
 | |
|     Rails.cache.delete("statuses/#{status_id}")
 | |
|   end
 | |
| 
 | |
|   def last_fetched_before_expiration?
 | |
|     last_fetched_at.nil? || expires_at.nil? || last_fetched_at < expires_at
 | |
|   end
 | |
| 
 | |
|   def time_passed_since_last_fetch?
 | |
|     last_fetched_at.nil? || last_fetched_at < 1.minute.ago
 | |
|   end
 | |
| 
 | |
|   def show_totals_now?
 | |
|     expired? || !hide_totals?
 | |
|   end
 | |
| end
 |