/
debate.rb
138 lines (111 loc) · 3.75 KB
/
debate.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
require 'numeric'
class Debate < ActiveRecord::Base
include Flaggable
include Taggable
include Conflictable
include Measurable
include Sanitizable
include PgSearch
apply_simple_captcha
acts_as_votable
acts_as_paranoid column: :hidden_at
include ActsAsParanoidAliases
belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
has_many :comments, as: :commentable
validates :title, presence: true
validates :description, presence: true
validates :author, presence: true
validates :title, length: { in: 4..Debate.title_max_length }
validates :description, length: { in: 10..Debate.description_max_length }
validates :terms_of_service, acceptance: { allow_nil: false }, on: :create
before_save :calculate_hot_score, :calculate_confidence_score
scope :for_render, -> { includes(:tags) }
scope :sort_by_hot_score , -> { order(hot_score: :desc) }
scope :sort_by_confidence_score , -> { order(confidence_score: :desc) }
scope :sort_by_created_at, -> { order(created_at: :desc) }
scope :sort_by_most_commented, -> { order(comments_count: :desc) }
scope :sort_by_random, -> { order("RANDOM()") }
scope :sort_by_flags, -> { order(flags_count: :desc, updated_at: :desc) }
# Ahoy setup
visitable # Ahoy will automatically assign visit_id on create
pg_search_scope :pg_search, {
against: {
title: 'A',
description: 'B'
},
associated_against: {
tags: :name
},
using: {
tsearch: { dictionary: "spanish" },
trigram: { threshold: 0.1 },
},
ranked_by: '(:tsearch + debates.cached_votes_up)',
order_within_rank: "debates.created_at DESC"
}
def description
super.try :html_safe
end
def likes
cached_votes_up
end
def dislikes
cached_votes_down
end
def total_votes
cached_votes_total
end
def total_anonymous_votes
cached_anonymous_votes_total
end
def editable?
created_at > 48.hours.ago
end
def editable_by?(user)
editable? && author == user
end
def register_vote(user, vote_value)
if votable_by?(user)
Debate.increment_counter(:cached_anonymous_votes_total, id) if (user.unverified? && !user.voted_for?(self))
vote_by(voter: user, vote: vote_value)
end
end
def votable_by?(user)
return false unless user
total_votes <= 100 ||
!user.unverified? ||
Setting.value_for('max_ratio_anon_votes_on_debates').to_i == 100 ||
anonymous_votes_ratio < Setting.value_for('max_ratio_anon_votes_on_debates').to_i ||
user.voted_for?(self)
end
def anonymous_votes_ratio
return 0 if cached_votes_total == 0
(cached_anonymous_votes_total.to_f / cached_votes_total) * 100
end
def after_commented
save # updates the hot_score because there is a before_save
end
def calculate_hot_score
self.hot_score = ScoreCalculator.hot_score(created_at,
cached_votes_total,
cached_votes_up,
comments_count)
end
def calculate_confidence_score
self.confidence_score = ScoreCalculator.confidence_score(cached_votes_total,
cached_votes_up)
end
def self.search(terms)
return none unless terms.present?
debate_ids = where("debates.title ILIKE ? OR debates.description ILIKE ?",
"%#{terms}%", "%#{terms}%").pluck(:id)
tag_ids = tagged_with(terms, wild: true, any: true).pluck(:id)
where(id: [debate_ids, tag_ids].flatten.compact)
end
def after_hide
self.tags.each{ |t| t.decrement_custom_counter_for('Debate') }
end
def after_restore
self.tags.each{ |t| t.increment_custom_counter_for('Debate') }
end
end