forgeplus/app/models/vote.rb

76 lines
2.0 KiB
Ruby

class Vote < ApplicationRecord
self.table_name = 'new_votes'
belongs_to :platform_communicate
has_many :vote_options, dependent: :destroy
has_many :user_vote_options, through: :vote_options
accepts_nested_attributes_for :vote_options, allow_destroy: true
validates :max_choice_vote_options_count,
numericality: {
greater_than: 1,
less_than_or_equal_to: 20,
allow_nil: true
},
if: :is_multiple_choice?
validate :validate_multiple_choice_settings
def expired?
due_at.present? && due_at < Time.current
end
def user_voted?(user)
return false unless user
user_vote_options.where(user_id: user.id).exists?
end
def user_selections(user)
return UserVoteOption.none unless user
user_vote_options.where(user_id: user.id)
end
def total_votes_count
# 计算参与投票的总人数(去重)
user_vote_options.select(:user_id).distinct.count
end
def total_votes_options_count
vote_options.sum(:user_vote_options_count)
end
# 获取投票结果(使用缓存字段,性能更好)
def results_with_cache
vote_options.select(:id, :title, :user_vote_options_count).map do |option|
{
id: option.id,
title: option.title,
vote_count: option.user_vote_options_count,
percentage: calculate_percentage_for_option(option.user_vote_options_count)
}
end
end
private
def calculate_percentage_for_option(option_votes)
total = total_votes_options_count
return 0 if total.zero?
(option_votes.to_f / total * 100).round(2)
end
def validate_multiple_choice_settings
if is_multiple_choice? && max_choice_vote_options_count.nil?
errors.add(:max_choice_vote_options_count, '多选投票必须设置最大选择数')
end
if !is_multiple_choice? && max_choice_vote_options_count.present?
errors.add(:max_choice_vote_options_count, '单选投票不需要设置最大选择数')
end
end
end