acts_as_votable 0.10.0 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +9 -6
- data/.rubocop.yml +121 -0
- data/.travis.yml +12 -23
- data/Appraisals +13 -0
- data/Gemfile +3 -14
- data/README.markdown +80 -13
- data/Rakefile +6 -4
- data/acts_as_votable.gemspec +12 -5
- data/gemfiles/.bundle/config +2 -0
- data/gemfiles/rails_4.gemfile +7 -0
- data/gemfiles/rails_4.gemfile.lock +159 -0
- data/gemfiles/rails_5.gemfile +7 -0
- data/gemfiles/rails_5.gemfile.lock +166 -0
- data/gemfiles/rails_5_1.gemfile +7 -0
- data/gemfiles/rails_5_1.gemfile.lock +166 -0
- data/lib/acts_as_votable.rb +9 -9
- data/lib/acts_as_votable/cacheable.rb +174 -0
- data/lib/acts_as_votable/extenders/controller.rb +3 -4
- data/lib/acts_as_votable/extenders/votable.rb +17 -6
- data/lib/acts_as_votable/extenders/voter.rb +4 -6
- data/lib/acts_as_votable/helpers/words.rb +7 -10
- data/lib/acts_as_votable/version.rb +3 -1
- data/lib/acts_as_votable/votable.rb +50 -187
- data/lib/acts_as_votable/vote.rb +10 -12
- data/lib/acts_as_votable/voter.rb +52 -53
- data/lib/generators/acts_as_votable/migration/migration_generator.rb +19 -4
- data/lib/generators/acts_as_votable/migration/templates/active_record/{migration.rb → migration.erb} +1 -6
- data/spec/factories/votable.rb +6 -0
- data/spec/factories/votable_cache.rb +6 -0
- data/spec/factories/votable_cache_update_attributes.rb +6 -0
- data/spec/factories/votable_cache_update_columns.rb +6 -0
- data/spec/factories/votable_child_of_sti_not_votable.rb +6 -0
- data/spec/factories/votable_child_of_sti_votable.rb +6 -0
- data/spec/factories/votable_voter.rb +6 -0
- data/spec/factories/vote.rb +6 -0
- data/spec/factories/voter.rb +6 -0
- data/spec/generators/active_record_generator_spec.rb +13 -0
- data/spec/shared_example/votable_model.rb +506 -0
- data/spec/shared_example/voter_model.rb +280 -0
- data/spec/spec_helper.rb +28 -18
- data/spec/support/factory_girl.rb +10 -0
- data/spec/votable_spec.rb +10 -9
- data/spec/votable_voter_spec.rb +12 -12
- data/spec/voter_spec.rb +9 -10
- data/spec/words_spec.rb +9 -12
- metadata +98 -27
- data/spec/shared_example/votable_model_spec.rb +0 -421
- data/spec/shared_example/voter_model_spec.rb +0 -279
data/lib/acts_as_votable.rb
CHANGED
@@ -1,21 +1,21 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_record"
|
4
|
+
require "active_support/inflector"
|
3
5
|
|
4
6
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
5
7
|
|
6
8
|
module ActsAsVotable
|
7
|
-
|
8
9
|
if defined?(ActiveRecord::Base)
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
10
|
+
require "acts_as_votable/extenders/votable"
|
11
|
+
require "acts_as_votable/extenders/voter"
|
12
|
+
require "acts_as_votable/vote"
|
12
13
|
ActiveRecord::Base.extend ActsAsVotable::Extenders::Votable
|
13
14
|
ActiveRecord::Base.extend ActsAsVotable::Extenders::Voter
|
14
15
|
end
|
15
|
-
|
16
16
|
end
|
17
17
|
|
18
|
-
require
|
18
|
+
require "acts_as_votable/extenders/controller"
|
19
19
|
ActiveSupport.on_load(:action_controller) do
|
20
20
|
include ActsAsVotable::Extenders::Controller
|
21
|
-
end
|
21
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActsAsVotable
|
4
|
+
module Cacheable
|
5
|
+
def scope_cache_field(field, vote_scope)
|
6
|
+
return field if vote_scope.nil?
|
7
|
+
|
8
|
+
case field
|
9
|
+
when :cached_votes_total=
|
10
|
+
"cached_scoped_#{vote_scope}_votes_total="
|
11
|
+
when :cached_votes_total
|
12
|
+
"cached_scoped_#{vote_scope}_votes_total"
|
13
|
+
when :cached_votes_up=
|
14
|
+
"cached_scoped_#{vote_scope}_votes_up="
|
15
|
+
when :cached_votes_up
|
16
|
+
"cached_scoped_#{vote_scope}_votes_up"
|
17
|
+
when :cached_votes_down=
|
18
|
+
"cached_scoped_#{vote_scope}_votes_down="
|
19
|
+
when :cached_votes_down
|
20
|
+
"cached_scoped_#{vote_scope}_votes_down"
|
21
|
+
when :cached_votes_score=
|
22
|
+
"cached_scoped_#{vote_scope}_votes_score="
|
23
|
+
when :cached_votes_score
|
24
|
+
"cached_scoped_#{vote_scope}_votes_score"
|
25
|
+
when :cached_weighted_total
|
26
|
+
"cached_weighted_#{vote_scope}_total"
|
27
|
+
when :cached_weighted_total=
|
28
|
+
"cached_weighted_#{vote_scope}_total="
|
29
|
+
when :cached_weighted_score
|
30
|
+
"cached_weighted_#{vote_scope}_score"
|
31
|
+
when :cached_weighted_score=
|
32
|
+
"cached_weighted_#{vote_scope}_score="
|
33
|
+
when :cached_weighted_average
|
34
|
+
"cached_weighted_#{vote_scope}_average"
|
35
|
+
when :cached_weighted_average=
|
36
|
+
"cached_weighted_#{vote_scope}_average="
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def update_cached_votes(vote_scope = nil)
|
41
|
+
updates = {}
|
42
|
+
|
43
|
+
if self.respond_to?(:cached_votes_total=)
|
44
|
+
updates[:cached_votes_total] = count_votes_total(true)
|
45
|
+
end
|
46
|
+
|
47
|
+
if self.respond_to?(:cached_votes_up=)
|
48
|
+
updates[:cached_votes_up] = count_votes_up(true)
|
49
|
+
end
|
50
|
+
|
51
|
+
if self.respond_to?(:cached_votes_down=)
|
52
|
+
updates[:cached_votes_down] = count_votes_down(true)
|
53
|
+
end
|
54
|
+
|
55
|
+
if self.respond_to?(:cached_votes_score=)
|
56
|
+
updates[:cached_votes_score] = (
|
57
|
+
(updates[:cached_votes_up] || count_votes_up(true)) -
|
58
|
+
(updates[:cached_votes_down] || count_votes_down(true))
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
if self.respond_to?(:cached_weighted_total=)
|
63
|
+
updates[:cached_weighted_total] = weighted_total(true)
|
64
|
+
end
|
65
|
+
|
66
|
+
if self.respond_to?(:cached_weighted_score=)
|
67
|
+
updates[:cached_weighted_score] = weighted_score(true)
|
68
|
+
end
|
69
|
+
|
70
|
+
if self.respond_to?(:cached_weighted_average=)
|
71
|
+
updates[:cached_weighted_average] = weighted_average(true)
|
72
|
+
end
|
73
|
+
|
74
|
+
if vote_scope
|
75
|
+
if self.respond_to?(scope_cache_field :cached_votes_total=, vote_scope)
|
76
|
+
updates[scope_cache_field :cached_votes_total, vote_scope] = count_votes_total(true, vote_scope)
|
77
|
+
end
|
78
|
+
|
79
|
+
if self.respond_to?(scope_cache_field :cached_votes_up=, vote_scope)
|
80
|
+
updates[scope_cache_field :cached_votes_up, vote_scope] = count_votes_up(true, vote_scope)
|
81
|
+
end
|
82
|
+
|
83
|
+
if self.respond_to?(scope_cache_field :cached_votes_down=, vote_scope)
|
84
|
+
updates[scope_cache_field :cached_votes_down, vote_scope] = count_votes_down(true, vote_scope)
|
85
|
+
end
|
86
|
+
|
87
|
+
if self.respond_to?(scope_cache_field :cached_weighted_total=, vote_scope)
|
88
|
+
updates[scope_cache_field :cached_weighted_total, vote_scope] = weighted_total(true, vote_scope)
|
89
|
+
end
|
90
|
+
|
91
|
+
if self.respond_to?(scope_cache_field :cached_weighted_score=, vote_scope)
|
92
|
+
updates[scope_cache_field :cached_weighted_score, vote_scope] = weighted_score(true, vote_scope)
|
93
|
+
end
|
94
|
+
|
95
|
+
if self.respond_to?(scope_cache_field :cached_votes_score=, vote_scope)
|
96
|
+
updates[scope_cache_field :cached_votes_score, vote_scope] = (
|
97
|
+
(updates[scope_cache_field :cached_votes_up, vote_scope] || count_votes_up(true, vote_scope)) -
|
98
|
+
(updates[scope_cache_field :cached_votes_down, vote_scope] || count_votes_down(true, vote_scope))
|
99
|
+
)
|
100
|
+
end
|
101
|
+
|
102
|
+
if self.respond_to?(scope_cache_field :cached_weighted_average=, vote_scope)
|
103
|
+
updates[scope_cache_field :cached_weighted_average, vote_scope] = weighted_average(true, vote_scope)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
self.send(acts_as_votable_options[:cacheable_strategy], updates) if updates.size > 0
|
108
|
+
end
|
109
|
+
|
110
|
+
# counting
|
111
|
+
def count_votes_total(skip_cache = false, vote_scope = nil)
|
112
|
+
from_cache(skip_cache, :cached_votes_total, vote_scope) do
|
113
|
+
find_votes_for(scope_or_empty_hash(vote_scope)).count
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def count_votes_up(skip_cache = false, vote_scope = nil)
|
118
|
+
from_cache(skip_cache, :cached_votes_up, vote_scope) do
|
119
|
+
get_up_votes(vote_scope: vote_scope).count
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def count_votes_down(skip_cache = false, vote_scope = nil)
|
124
|
+
from_cache(skip_cache, :cached_votes_down, vote_scope) do
|
125
|
+
get_down_votes(vote_scope: vote_scope).count
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def count_votes_score(skip_cache = false, vote_scope = nil)
|
130
|
+
from_cache(skip_cache, :cached_votes_score, vote_scope) do
|
131
|
+
ups = count_votes_up(true, vote_scope)
|
132
|
+
downs = count_votes_down(true, vote_scope)
|
133
|
+
ups - downs
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def weighted_total(skip_cache = false, vote_scope = nil)
|
138
|
+
from_cache(skip_cache, :cached_weighted_total, vote_scope) do
|
139
|
+
ups = get_up_votes(vote_scope: vote_scope).sum(:vote_weight)
|
140
|
+
downs = get_down_votes(vote_scope: vote_scope).sum(:vote_weight)
|
141
|
+
ups + downs
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def weighted_score(skip_cache = false, vote_scope = nil)
|
146
|
+
from_cache(skip_cache, :cached_weighted_score, vote_scope) do
|
147
|
+
ups = get_up_votes(vote_scope: vote_scope).sum(:vote_weight)
|
148
|
+
downs = get_down_votes(vote_scope: vote_scope).sum(:vote_weight)
|
149
|
+
ups - downs
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def weighted_average(skip_cache = false, vote_scope = nil)
|
154
|
+
from_cache(skip_cache, :cached_weighted_average, vote_scope) do
|
155
|
+
count = count_votes_total(skip_cache, vote_scope).to_i
|
156
|
+
if count > 0
|
157
|
+
weighted_score(skip_cache, vote_scope).to_f / count
|
158
|
+
else
|
159
|
+
0.0
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
private
|
165
|
+
|
166
|
+
def from_cache(skip_cache, cached_method, vote_scope)
|
167
|
+
if !skip_cache && respond_to?(scope_cache_field(cached_method, vote_scope))
|
168
|
+
send(scope_cache_field(cached_method, vote_scope))
|
169
|
+
else
|
170
|
+
yield
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -1,19 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActsAsVotable
|
2
4
|
module Extenders
|
3
|
-
|
4
5
|
module Controller
|
5
|
-
|
6
6
|
def voter_params(params_object = params[:vote])
|
7
7
|
params_object.permit(:votable_id, :votable_type,
|
8
8
|
:voter_id, :voter_type,
|
9
9
|
:votable, :voter,
|
10
10
|
:vote_flag, :vote_scope)
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
def votable_params(params_object = params[:vote])
|
14
14
|
params_object.permit(:vote_registered)
|
15
15
|
end
|
16
|
-
|
17
16
|
end
|
18
17
|
end
|
19
18
|
end
|
@@ -1,25 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActsAsVotable
|
2
4
|
module Extenders
|
3
|
-
|
4
5
|
module Votable
|
6
|
+
ALLOWED_CACHEABLE_STRATEGIES = %i[update_attributes update_columns]
|
5
7
|
|
6
8
|
def votable?
|
7
9
|
false
|
8
10
|
end
|
9
11
|
|
10
|
-
def acts_as_votable
|
11
|
-
require
|
12
|
+
def acts_as_votable(args = {})
|
13
|
+
require "acts_as_votable/votable"
|
12
14
|
include ActsAsVotable::Votable
|
13
15
|
|
16
|
+
if args.key?(:cacheable_strategy) && !ALLOWED_CACHEABLE_STRATEGIES.include?(args[:cacheable_strategy])
|
17
|
+
raise ArgumentError, args[:cacheable_strategy]
|
18
|
+
end
|
19
|
+
|
20
|
+
define_method :acts_as_votable_options do
|
21
|
+
self.class.instance_variable_get("@acts_as_votable_options")
|
22
|
+
end
|
23
|
+
|
14
24
|
class_eval do
|
25
|
+
@acts_as_votable_options = {
|
26
|
+
cacheable_strategy: :update_attributes
|
27
|
+
}.merge(args)
|
28
|
+
|
15
29
|
def self.votable?
|
16
30
|
true
|
17
31
|
end
|
18
32
|
end
|
19
|
-
|
20
33
|
end
|
21
|
-
|
22
34
|
end
|
23
|
-
|
24
35
|
end
|
25
36
|
end
|
@@ -1,14 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActsAsVotable
|
2
4
|
module Extenders
|
3
|
-
|
4
5
|
module Voter
|
5
|
-
|
6
6
|
def voter?
|
7
7
|
false
|
8
8
|
end
|
9
9
|
|
10
|
-
def acts_as_voter(*
|
11
|
-
require
|
10
|
+
def acts_as_voter(*_args)
|
11
|
+
require "acts_as_votable/voter"
|
12
12
|
include ActsAsVotable::Voter
|
13
13
|
|
14
14
|
class_eval do
|
@@ -16,9 +16,7 @@ module ActsAsVotable
|
|
16
16
|
true
|
17
17
|
end
|
18
18
|
end
|
19
|
-
|
20
19
|
end
|
21
|
-
|
22
20
|
end
|
23
21
|
end
|
24
22
|
end
|
@@ -1,36 +1,33 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
module ActsAsVotable::Helpers
|
4
|
+
# this helper provides methods that help find what words are
|
4
5
|
# up votes and what words are down votes
|
5
6
|
#
|
6
|
-
# It can be called
|
7
|
+
# It can be called
|
7
8
|
#
|
8
9
|
# votable_object.votable_words.that_mean_true
|
9
10
|
#
|
10
11
|
module Words
|
11
|
-
|
12
12
|
def votable_words
|
13
13
|
VotableWords
|
14
14
|
end
|
15
|
-
|
16
15
|
end
|
17
16
|
|
18
17
|
class VotableWords
|
19
|
-
|
20
18
|
def self.that_mean_true
|
21
|
-
[
|
19
|
+
["up", "upvote", "like", "liked", "positive", "yes", "good", "agree", "true", 1, true]
|
22
20
|
end
|
23
21
|
|
24
22
|
def self.that_mean_false
|
25
|
-
[
|
23
|
+
["down", "downvote", "dislike", "disliked", "negative", "no", "bad", "disagree", "false", 0, false]
|
26
24
|
end
|
27
25
|
|
28
26
|
# check is word is a true or bad vote
|
29
27
|
# if the word is unknown, then it counts it as a true/good
|
30
28
|
# vote. this exists to allow all voting to be good by default
|
31
|
-
def self.meaning_of
|
29
|
+
def self.meaning_of(word)
|
32
30
|
!that_mean_false.include?(word)
|
33
31
|
end
|
34
|
-
|
35
32
|
end
|
36
33
|
end
|
@@ -1,39 +1,41 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "acts_as_votable/helpers/words"
|
4
|
+
require "acts_as_votable/cacheable"
|
2
5
|
|
3
6
|
module ActsAsVotable
|
4
7
|
module Votable
|
5
|
-
|
6
8
|
include Helpers::Words
|
9
|
+
include Cacheable
|
7
10
|
|
8
|
-
def self.included
|
9
|
-
|
11
|
+
def self.included(base)
|
10
12
|
# allow the user to define these himself
|
11
13
|
aliases = {
|
12
14
|
|
13
|
-
:
|
14
|
-
:up_by, :upvote_by, :like_by, :liked_by,
|
15
|
+
vote_up: [
|
16
|
+
:up_by, :upvote_by, :like_by, :liked_by,
|
15
17
|
:up_from, :upvote_from, :upvote_by, :like_from, :liked_from, :vote_from
|
16
18
|
],
|
17
19
|
|
18
|
-
:
|
20
|
+
vote_down: [
|
19
21
|
:down_by, :downvote_by, :dislike_by, :disliked_by,
|
20
22
|
:down_from, :downvote_from, :downvote_by, :dislike_by, :disliked_by
|
21
23
|
],
|
22
24
|
|
23
|
-
:
|
25
|
+
get_up_votes: [
|
24
26
|
:get_true_votes, :get_ups, :get_upvotes, :get_likes, :get_positives, :get_for_votes,
|
25
27
|
],
|
26
28
|
|
27
|
-
:
|
29
|
+
get_down_votes: [
|
28
30
|
:get_false_votes, :get_downs, :get_downvotes, :get_dislikes, :get_negatives
|
29
31
|
],
|
30
|
-
:
|
32
|
+
unvote_by: [
|
31
33
|
:unvote_up, :unvote_down, :unliked_by, :undisliked_by
|
32
34
|
]
|
33
35
|
}
|
34
36
|
|
35
37
|
base.class_eval do
|
36
|
-
has_many :votes_for, :
|
38
|
+
has_many :votes_for, class_name: "ActsAsVotable::Vote", as: :votable, dependent: :destroy do
|
37
39
|
def voters
|
38
40
|
includes(:voter).map(&:voter)
|
39
41
|
end
|
@@ -56,17 +58,16 @@ module ActsAsVotable
|
|
56
58
|
|
57
59
|
def default_conditions
|
58
60
|
{
|
59
|
-
:
|
60
|
-
:
|
61
|
+
votable_id: self.id,
|
62
|
+
votable_type: self.class.base_class.name.to_s
|
61
63
|
}
|
62
64
|
end
|
63
65
|
|
64
66
|
# voting
|
65
|
-
def vote_by
|
66
|
-
|
67
|
+
def vote_by(args = {})
|
67
68
|
options = {
|
68
|
-
:
|
69
|
-
:
|
69
|
+
vote: true,
|
70
|
+
vote_scope: nil
|
70
71
|
}.merge(args)
|
71
72
|
|
72
73
|
self.vote_registered = false
|
@@ -76,22 +77,20 @@ module ActsAsVotable
|
|
76
77
|
end
|
77
78
|
|
78
79
|
# find the vote
|
79
|
-
|
80
|
-
:
|
81
|
-
:
|
82
|
-
:voter_type => options[:voter].class.base_class.name
|
83
|
-
})
|
80
|
+
votes = find_votes_for(voter_id: options[:voter].id,
|
81
|
+
vote_scope: options[:vote_scope],
|
82
|
+
voter_type: options[:voter].class.base_class.name)
|
84
83
|
|
85
|
-
if
|
84
|
+
if votes.count == (0) || options[:duplicate]
|
86
85
|
# this voter has never voted
|
87
86
|
vote = ActsAsVotable::Vote.new(
|
88
|
-
:
|
89
|
-
:
|
90
|
-
:
|
87
|
+
votable: self,
|
88
|
+
voter: options[:voter],
|
89
|
+
vote_scope: options[:vote_scope]
|
91
90
|
)
|
92
91
|
else
|
93
92
|
# this voter is potentially changing his vote
|
94
|
-
vote =
|
93
|
+
vote = votes.last
|
95
94
|
end
|
96
95
|
|
97
96
|
last_update = vote.updated_at
|
@@ -109,192 +108,56 @@ module ActsAsVotable
|
|
109
108
|
self.vote_registered = false
|
110
109
|
return false
|
111
110
|
end
|
112
|
-
|
113
111
|
end
|
114
112
|
|
115
|
-
def unvote
|
113
|
+
def unvote(args = {})
|
116
114
|
return false if args[:voter].nil?
|
117
|
-
|
115
|
+
votes = find_votes_for(voter_id: args[:voter].id, vote_scope: args[:vote_scope], voter_type: args[:voter].class.base_class.name)
|
118
116
|
|
119
|
-
return true if
|
120
|
-
|
117
|
+
return true if votes.size == 0
|
118
|
+
votes.each(&:destroy)
|
121
119
|
update_cached_votes args[:vote_scope]
|
122
120
|
self.vote_registered = false if votes_for.count == 0
|
123
121
|
return true
|
124
122
|
end
|
125
123
|
|
126
|
-
def vote_up
|
127
|
-
self.vote_by :
|
128
|
-
end
|
129
|
-
|
130
|
-
def vote_down voter, options={}
|
131
|
-
self.vote_by :voter => voter, :vote => false, :vote_scope => options[:vote_scope], :vote_weight => options[:vote_weight]
|
124
|
+
def vote_up(voter, options = {})
|
125
|
+
self.vote_by voter: voter, vote: true, vote_scope: options[:vote_scope], vote_weight: options[:vote_weight]
|
132
126
|
end
|
133
127
|
|
134
|
-
def
|
135
|
-
self.
|
128
|
+
def vote_down(voter, options = {})
|
129
|
+
self.vote_by voter: voter, vote: false, vote_scope: options[:vote_scope], vote_weight: options[:vote_weight]
|
136
130
|
end
|
137
131
|
|
138
|
-
def
|
139
|
-
|
140
|
-
|
141
|
-
case field
|
142
|
-
when :cached_votes_total=
|
143
|
-
"cached_scoped_#{vote_scope}_votes_total="
|
144
|
-
when :cached_votes_total
|
145
|
-
"cached_scoped_#{vote_scope}_votes_total"
|
146
|
-
when :cached_votes_up=
|
147
|
-
"cached_scoped_#{vote_scope}_votes_up="
|
148
|
-
when :cached_votes_up
|
149
|
-
"cached_scoped_#{vote_scope}_votes_up"
|
150
|
-
when :cached_votes_down=
|
151
|
-
"cached_scoped_#{vote_scope}_votes_down="
|
152
|
-
when :cached_votes_down
|
153
|
-
"cached_scoped_#{vote_scope}_votes_down"
|
154
|
-
when :cached_votes_score=
|
155
|
-
"cached_scoped_#{vote_scope}_votes_score="
|
156
|
-
when :cached_votes_score
|
157
|
-
"cached_scoped_#{vote_scope}_votes_score"
|
158
|
-
when :cached_weighted_total
|
159
|
-
"cached_weighted_#{vote_scope}_total"
|
160
|
-
when :cached_weighted_total=
|
161
|
-
"cached_weighted_#{vote_scope}_total="
|
162
|
-
when :cached_weighted_score
|
163
|
-
"cached_weighted_#{vote_scope}_score"
|
164
|
-
when :cached_weighted_score=
|
165
|
-
"cached_weighted_#{vote_scope}_score="
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
# caching
|
170
|
-
def update_cached_votes vote_scope = nil
|
171
|
-
|
172
|
-
updates = {}
|
173
|
-
|
174
|
-
if self.respond_to?(:cached_votes_total=)
|
175
|
-
updates[:cached_votes_total] = count_votes_total(true)
|
176
|
-
end
|
177
|
-
|
178
|
-
if self.respond_to?(:cached_votes_up=)
|
179
|
-
updates[:cached_votes_up] = count_votes_up(true)
|
180
|
-
end
|
181
|
-
|
182
|
-
if self.respond_to?(:cached_votes_down=)
|
183
|
-
updates[:cached_votes_down] = count_votes_down(true)
|
184
|
-
end
|
185
|
-
|
186
|
-
if self.respond_to?(:cached_votes_score=)
|
187
|
-
updates[:cached_votes_score] = (
|
188
|
-
(updates[:cached_votes_up] || count_votes_up(true)) -
|
189
|
-
(updates[:cached_votes_down] || count_votes_down(true))
|
190
|
-
)
|
191
|
-
end
|
192
|
-
|
193
|
-
if self.respond_to?(:cached_weighted_total=)
|
194
|
-
updates[:cached_weighted_total] = weighted_total(true)
|
195
|
-
end
|
196
|
-
|
197
|
-
if self.respond_to?(:cached_weighted_score=)
|
198
|
-
updates[:cached_weighted_score] = weighted_score(true)
|
199
|
-
end
|
200
|
-
|
201
|
-
if vote_scope
|
202
|
-
if self.respond_to?(scope_cache_field :cached_votes_total=, vote_scope)
|
203
|
-
updates[scope_cache_field :cached_votes_total, vote_scope] = count_votes_total(true, vote_scope)
|
204
|
-
end
|
205
|
-
|
206
|
-
if self.respond_to?(scope_cache_field :cached_votes_up=, vote_scope)
|
207
|
-
updates[scope_cache_field :cached_votes_up, vote_scope] = count_votes_up(true, vote_scope)
|
208
|
-
end
|
209
|
-
|
210
|
-
if self.respond_to?(scope_cache_field :cached_votes_down=, vote_scope)
|
211
|
-
updates[scope_cache_field :cached_votes_down, vote_scope] = count_votes_down(true, vote_scope)
|
212
|
-
end
|
213
|
-
|
214
|
-
if self.respond_to?(scope_cache_field :cached_weighted_total=, vote_scope)
|
215
|
-
updates[scope_cache_field :cached_weighted_total, vote_scope] = weighted_total(true, vote_scope)
|
216
|
-
end
|
217
|
-
|
218
|
-
if self.respond_to?(scope_cache_field :cached_weighted_score=, vote_scope)
|
219
|
-
updates[scope_cache_field :cached_weighted_score, vote_scope] = weighted_score(true, vote_scope)
|
220
|
-
end
|
221
|
-
|
222
|
-
if self.respond_to?(scope_cache_field :cached_votes_score=, vote_scope)
|
223
|
-
updates[scope_cache_field :cached_votes_score, vote_scope] = (
|
224
|
-
(updates[scope_cache_field :cached_votes_up, vote_scope] || count_votes_up(true, vote_scope)) -
|
225
|
-
(updates[scope_cache_field :cached_votes_down, vote_scope] || count_votes_down(true, vote_scope))
|
226
|
-
)
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
if (::ActiveRecord::VERSION::MAJOR == 3) && (::ActiveRecord::VERSION::MINOR != 0)
|
231
|
-
self.update_attributes(updates, :without_protection => true) if updates.size > 0
|
232
|
-
else
|
233
|
-
self.update_attributes(updates) if updates.size > 0
|
234
|
-
end
|
235
|
-
|
132
|
+
def unvote_by(voter, options = {})
|
133
|
+
self.unvote voter: voter, vote_scope: options[:vote_scope] #Does not need vote_weight since the votes_for are anyway getting destroyed
|
236
134
|
end
|
237
135
|
|
238
|
-
|
239
136
|
# results
|
240
|
-
def find_votes_for
|
137
|
+
def find_votes_for(extra_conditions = {})
|
241
138
|
votes_for.where(extra_conditions)
|
242
139
|
end
|
243
140
|
|
244
|
-
def get_up_votes
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
def get_down_votes options={}
|
249
|
-
find_votes_for(:vote_flag => false, :vote_scope => options[:vote_scope])
|
250
|
-
end
|
251
|
-
|
252
|
-
|
253
|
-
# counting
|
254
|
-
def count_votes_total skip_cache = false, vote_scope = nil
|
255
|
-
if !skip_cache && self.respond_to?(scope_cache_field :cached_votes_total, vote_scope)
|
256
|
-
return self.send(scope_cache_field :cached_votes_total, vote_scope)
|
257
|
-
end
|
258
|
-
find_votes_for(:vote_scope => vote_scope).count
|
259
|
-
end
|
260
|
-
|
261
|
-
def count_votes_up skip_cache = false, vote_scope = nil
|
262
|
-
if !skip_cache && self.respond_to?(scope_cache_field :cached_votes_up, vote_scope)
|
263
|
-
return self.send(scope_cache_field :cached_votes_up, vote_scope)
|
264
|
-
end
|
265
|
-
get_up_votes(:vote_scope => vote_scope).count
|
141
|
+
def get_up_votes(options = {})
|
142
|
+
vote_scope_hash = scope_or_empty_hash(options[:vote_scope])
|
143
|
+
find_votes_for({ vote_flag: true }.merge(vote_scope_hash))
|
266
144
|
end
|
267
145
|
|
268
|
-
def
|
269
|
-
|
270
|
-
|
271
|
-
end
|
272
|
-
get_down_votes(:vote_scope => vote_scope).count
|
273
|
-
end
|
274
|
-
|
275
|
-
def weighted_total skip_cache = false, vote_scope = nil
|
276
|
-
if !skip_cache && self.respond_to?(scope_cache_field :cached_weighted_total, vote_scope)
|
277
|
-
return self.send(scope_cache_field :cached_weighted_total, vote_scope)
|
278
|
-
end
|
279
|
-
ups = get_up_votes(:vote_scope => vote_scope).sum(:vote_weight)
|
280
|
-
downs = get_down_votes(:vote_scope => vote_scope).sum(:vote_weight)
|
281
|
-
ups + downs
|
282
|
-
end
|
283
|
-
|
284
|
-
def weighted_score skip_cache = false, vote_scope = nil
|
285
|
-
if !skip_cache && self.respond_to?(scope_cache_field :cached_weighted_score, vote_scope)
|
286
|
-
return self.send(scope_cache_field :cached_weighted_score, vote_scope)
|
287
|
-
end
|
288
|
-
ups = get_up_votes(:vote_scope => vote_scope).sum(:vote_weight)
|
289
|
-
downs = get_down_votes(:vote_scope => vote_scope).sum(:vote_weight)
|
290
|
-
ups - downs
|
146
|
+
def get_down_votes(options = {})
|
147
|
+
vote_scope_hash = scope_or_empty_hash(options[:vote_scope])
|
148
|
+
find_votes_for({ vote_flag: false }.merge(vote_scope_hash))
|
291
149
|
end
|
292
150
|
|
293
151
|
# voters
|
294
|
-
def voted_on_by?
|
295
|
-
votes = find_votes_for :
|
152
|
+
def voted_on_by?(voter)
|
153
|
+
votes = find_votes_for voter_id: voter.id, voter_type: voter.class.base_class.name
|
296
154
|
votes.count > 0
|
297
155
|
end
|
298
156
|
|
157
|
+
private
|
158
|
+
|
159
|
+
def scope_or_empty_hash(vote_scope)
|
160
|
+
vote_scope ? { vote_scope: vote_scope } : {}
|
161
|
+
end
|
299
162
|
end
|
300
163
|
end
|