acts_as_votable 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/vote.rb
CHANGED
@@ -1,29 +1,27 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "acts_as_votable/helpers/words"
|
2
4
|
|
3
5
|
module ActsAsVotable
|
4
6
|
class Vote < ::ActiveRecord::Base
|
5
|
-
|
6
7
|
include Helpers::Words
|
7
8
|
|
8
|
-
if
|
9
|
+
if defined?(ProtectedAttributes)
|
9
10
|
attr_accessible :votable_id, :votable_type,
|
10
11
|
:voter_id, :voter_type,
|
11
12
|
:votable, :voter,
|
12
13
|
:vote_flag, :vote_scope
|
13
14
|
end
|
14
15
|
|
15
|
-
belongs_to :votable, :
|
16
|
-
belongs_to :voter, :
|
16
|
+
belongs_to :votable, polymorphic: true
|
17
|
+
belongs_to :voter, polymorphic: true
|
17
18
|
|
18
|
-
scope :up,
|
19
|
-
scope :down,
|
20
|
-
scope :for_type,
|
21
|
-
scope :by_type,
|
19
|
+
scope :up, -> { where(vote_flag: true) }
|
20
|
+
scope :down, -> { where(vote_flag: false) }
|
21
|
+
scope :for_type, ->(klass) { where(votable_type: klass.to_s) }
|
22
|
+
scope :by_type, ->(klass) { where(voter_type: klass.to_s) }
|
22
23
|
|
23
24
|
validates_presence_of :votable_id
|
24
25
|
validates_presence_of :voter_id
|
25
|
-
|
26
26
|
end
|
27
|
-
|
28
27
|
end
|
29
|
-
|
@@ -1,24 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActsAsVotable
|
2
4
|
module Voter
|
3
|
-
|
4
5
|
def self.included(base)
|
5
|
-
|
6
6
|
# allow user to define these
|
7
7
|
aliases = {
|
8
|
-
:
|
9
|
-
:
|
10
|
-
:
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
:
|
15
|
-
:
|
16
|
-
:
|
8
|
+
vote_up_for: [:likes, :upvotes, :up_votes],
|
9
|
+
vote_down_for: [:dislikes, :downvotes, :down_votes],
|
10
|
+
unvote_for: [:unlike, :undislike],
|
11
|
+
voted_on?: [:voted_for?],
|
12
|
+
voted_up_on?: [:voted_up_for?, :liked?],
|
13
|
+
voted_down_on?: [:voted_down_for?, :disliked?],
|
14
|
+
voted_as_when_voting_on: [:voted_as_when_voted_on, :voted_as_when_voting_for, :voted_as_when_voted_for],
|
15
|
+
find_up_voted_items: [:find_liked_items],
|
16
|
+
find_down_voted_items: [:find_disliked_items]
|
17
17
|
}
|
18
18
|
|
19
19
|
base.class_eval do
|
20
20
|
|
21
|
-
has_many :votes, :
|
21
|
+
has_many :votes, class_name: "ActsAsVotable::Vote", as: :voter, dependent: :destroy do
|
22
22
|
def votables
|
23
23
|
includes(:votable).map(&:votable)
|
24
24
|
end
|
@@ -31,74 +31,73 @@ module ActsAsVotable
|
|
31
31
|
end
|
32
32
|
|
33
33
|
end
|
34
|
-
|
35
34
|
end
|
36
35
|
|
37
36
|
# voting
|
38
|
-
def vote
|
39
|
-
args[:votable].vote_by args.merge(
|
37
|
+
def vote(args)
|
38
|
+
args[:votable].vote_by args.merge(voter: self)
|
40
39
|
end
|
41
40
|
|
42
|
-
def vote_up_for
|
43
|
-
vote :
|
41
|
+
def vote_up_for(model = nil, args = {})
|
42
|
+
vote votable: model, vote_scope: args[:vote_scope], vote: true
|
44
43
|
end
|
45
44
|
|
46
|
-
def vote_down_for
|
47
|
-
vote :
|
45
|
+
def vote_down_for(model = nil, args = {})
|
46
|
+
vote votable: model, vote_scope: args[:vote_scope], vote: false
|
48
47
|
end
|
49
48
|
|
50
|
-
def unvote_for
|
51
|
-
model.unvote :
|
49
|
+
def unvote_for(model, args = {})
|
50
|
+
model.unvote voter: self, vote_scope: args[:vote_scope]
|
52
51
|
end
|
53
52
|
|
54
53
|
# results
|
55
|
-
def voted_on?
|
56
|
-
votes = find_votes(:
|
57
|
-
:
|
54
|
+
def voted_on?(votable, args = {})
|
55
|
+
votes = find_votes(votable_id: votable.id, votable_type: votable.class.base_class.name,
|
56
|
+
vote_scope: args[:vote_scope])
|
58
57
|
votes.size > 0
|
59
58
|
end
|
60
59
|
|
61
|
-
def voted_up_on?
|
62
|
-
votes = find_votes(:
|
63
|
-
:
|
60
|
+
def voted_up_on?(votable, args = {})
|
61
|
+
votes = find_votes(votable_id: votable.id, votable_type: votable.class.base_class.name,
|
62
|
+
vote_scope: args[:vote_scope], vote_flag: true)
|
64
63
|
votes.size > 0
|
65
64
|
end
|
66
65
|
|
67
|
-
def voted_down_on?
|
68
|
-
votes = find_votes(:
|
69
|
-
:
|
66
|
+
def voted_down_on?(votable, args = {})
|
67
|
+
votes = find_votes(votable_id: votable.id, votable_type: votable.class.base_class.name,
|
68
|
+
vote_scope: args[:vote_scope], vote_flag: false)
|
70
69
|
votes.size > 0
|
71
70
|
end
|
72
71
|
|
73
|
-
def voted_as_when_voting_on
|
74
|
-
vote = find_votes(:
|
75
|
-
:
|
72
|
+
def voted_as_when_voting_on(votable, args = {})
|
73
|
+
vote = find_votes(votable_id: votable.id, votable_type: votable.class.base_class.name,
|
74
|
+
vote_scope: args[:vote_scope]).select(:vote_flag).last
|
76
75
|
return nil unless vote
|
77
76
|
return vote.vote_flag
|
78
77
|
end
|
79
78
|
|
80
|
-
def find_votes
|
79
|
+
def find_votes(extra_conditions = {})
|
81
80
|
votes.where(extra_conditions)
|
82
81
|
end
|
83
82
|
|
84
|
-
def find_up_votes
|
85
|
-
find_votes :
|
83
|
+
def find_up_votes(args = {})
|
84
|
+
find_votes vote_flag: true, vote_scope: args[:vote_scope]
|
86
85
|
end
|
87
86
|
|
88
|
-
def find_down_votes
|
89
|
-
find_votes :
|
87
|
+
def find_down_votes(args = {})
|
88
|
+
find_votes vote_flag: false, vote_scope: args[:vote_scope]
|
90
89
|
end
|
91
90
|
|
92
|
-
def find_votes_for_class
|
93
|
-
find_votes extra_conditions.merge(
|
91
|
+
def find_votes_for_class(klass, extra_conditions = {})
|
92
|
+
find_votes extra_conditions.merge(votable_type: klass.name)
|
94
93
|
end
|
95
94
|
|
96
|
-
def find_up_votes_for_class
|
97
|
-
find_votes_for_class klass, :
|
95
|
+
def find_up_votes_for_class(klass, args = {})
|
96
|
+
find_votes_for_class klass, vote_flag: true, vote_scope: args[:vote_scope]
|
98
97
|
end
|
99
98
|
|
100
|
-
def find_down_votes_for_class
|
101
|
-
find_votes_for_class klass, :
|
99
|
+
def find_down_votes_for_class(klass, args = {})
|
100
|
+
find_votes_for_class klass, vote_flag: false, vote_scope: args[:vote_scope]
|
102
101
|
end
|
103
102
|
|
104
103
|
# Including polymporphic relations for eager loading
|
@@ -106,28 +105,28 @@ module ActsAsVotable
|
|
106
105
|
ActsAsVotable::Vote.includes(:votable)
|
107
106
|
end
|
108
107
|
|
109
|
-
def find_voted_items
|
110
|
-
options = extra_conditions.merge :
|
108
|
+
def find_voted_items(extra_conditions = {})
|
109
|
+
options = extra_conditions.merge voter_id: id, voter_type: self.class.base_class.name
|
111
110
|
include_objects.where(options).collect(&:votable)
|
112
111
|
end
|
113
112
|
|
114
|
-
def find_up_voted_items
|
115
|
-
find_voted_items extra_conditions.merge(:
|
113
|
+
def find_up_voted_items(extra_conditions = {})
|
114
|
+
find_voted_items extra_conditions.merge(vote_flag: true)
|
116
115
|
end
|
117
116
|
|
118
|
-
def find_down_voted_items
|
119
|
-
find_voted_items extra_conditions.merge(:
|
117
|
+
def find_down_voted_items(extra_conditions = {})
|
118
|
+
find_voted_items extra_conditions.merge(vote_flag: false)
|
120
119
|
end
|
121
120
|
|
122
|
-
def get_voted
|
121
|
+
def get_voted(klass, extra_conditions = {})
|
123
122
|
klass.joins(:votes_for).merge find_votes(extra_conditions)
|
124
123
|
end
|
125
124
|
|
126
|
-
def get_up_voted
|
125
|
+
def get_up_voted(klass)
|
127
126
|
klass.joins(:votes_for).merge find_up_votes
|
128
127
|
end
|
129
128
|
|
130
|
-
def get_down_voted
|
129
|
+
def get_down_voted(klass)
|
131
130
|
klass.joins(:votes_for).merge find_down_votes
|
132
131
|
end
|
133
132
|
end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails/generators/migration"
|
2
4
|
|
3
5
|
module ActsAsVotable
|
4
6
|
class MigrationGenerator < Rails::Generators::Base
|
@@ -11,21 +13,34 @@ module ActsAsVotable
|
|
11
13
|
end
|
12
14
|
|
13
15
|
def self.source_root
|
14
|
-
File.join(File.dirname(__FILE__),
|
16
|
+
File.join(File.dirname(__FILE__), "templates", (orm.to_s unless orm.class.eql?(String)))
|
15
17
|
end
|
16
18
|
|
17
19
|
def self.orm_has_migration?
|
18
20
|
[:active_record].include? orm
|
19
21
|
end
|
20
22
|
|
21
|
-
def self.next_migration_number(
|
23
|
+
def self.next_migration_number(_path)
|
22
24
|
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
23
25
|
end
|
24
26
|
|
25
27
|
def create_migration_file
|
26
28
|
if self.class.orm_has_migration?
|
27
|
-
migration_template
|
29
|
+
migration_template "migration.rb", "db/migrate/acts_as_votable_migration.rb", migration_version: migration_version
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def migration_version
|
37
|
+
if rails5?
|
38
|
+
"[4.2]"
|
28
39
|
end
|
29
40
|
end
|
41
|
+
|
42
|
+
def rails5?
|
43
|
+
Rails.version.start_with? "5"
|
44
|
+
end
|
30
45
|
end
|
31
46
|
end
|
data/lib/generators/acts_as_votable/migration/templates/active_record/{migration.rb → migration.erb}
RENAMED
@@ -1,4 +1,4 @@
|
|
1
|
-
class ActsAsVotableMigration < ActiveRecord::Migration
|
1
|
+
class ActsAsVotableMigration < ActiveRecord::Migration<%= migration_version %>
|
2
2
|
def self.up
|
3
3
|
create_table :votes do |t|
|
4
4
|
|
@@ -12,11 +12,6 @@ class ActsAsVotableMigration < ActiveRecord::Migration
|
|
12
12
|
t.timestamps
|
13
13
|
end
|
14
14
|
|
15
|
-
if ActiveRecord::VERSION::MAJOR < 4
|
16
|
-
add_index :votes, [:votable_id, :votable_type]
|
17
|
-
add_index :votes, [:voter_id, :voter_type]
|
18
|
-
end
|
19
|
-
|
20
15
|
add_index :votes, [:voter_id, :voter_type, :vote_scope]
|
21
16
|
add_index :votes, [:votable_id, :votable_type, :vote_scope]
|
22
17
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "acts_as_votable"
|
4
|
+
require "spec_helper"
|
5
|
+
|
6
|
+
require "rails/generators"
|
7
|
+
require "generators/acts_as_votable/migration/migration_generator"
|
8
|
+
|
9
|
+
module ActsAsVotable
|
10
|
+
describe MigrationGenerator do
|
11
|
+
pending
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,506 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
shared_examples "a votable_model" do
|
4
|
+
it "should return false when a vote with no voter is saved" do
|
5
|
+
expect(votable.vote_by).to be false
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should have one vote when saved" do
|
9
|
+
votable.vote_by voter: voter, vote: "yes"
|
10
|
+
expect(votable.votes_for.size).to eq(1)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should have one vote when voted on twice by the same person" do
|
14
|
+
votable.vote_by voter: voter, vote: "yes"
|
15
|
+
votable.vote_by voter: voter, vote: "no"
|
16
|
+
expect(votable.votes_for.size).to eq(1)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should have two votes_for when voted on twice by the same person with duplicate paramenter" do
|
20
|
+
votable.vote_by voter: voter, vote: "yes"
|
21
|
+
votable.vote_by voter: voter, vote: "no", duplicate: true
|
22
|
+
expect(votable.votes_for.size).to eq(2)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should have one scoped vote when voting under an scope" do
|
26
|
+
votable.vote_by voter: voter, vote: "yes", vote_scope: "rank"
|
27
|
+
expect(votable.find_votes_for(vote_scope: "rank").size).to eq(1)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should have one vote when voted on twice using scope by the same person" do
|
31
|
+
votable.vote_by voter: voter, vote: "yes", vote_scope: "rank"
|
32
|
+
votable.vote_by voter: voter, vote: "no", vote_scope: "rank"
|
33
|
+
expect(votable.find_votes_for(vote_scope: "rank").size).to eq(1)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should have two votes_for when voting on two different scopes by the same person" do
|
37
|
+
votable.vote_by voter: voter, vote: "yes", vote_scope: "weekly_rank"
|
38
|
+
votable.vote_by voter: voter, vote: "no", vote_scope: "monthly_rank"
|
39
|
+
expect(votable.votes_for.size).to eq(2)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should be callable with vote_up" do
|
43
|
+
votable.vote_up voter
|
44
|
+
expect(votable.get_up_votes.first.voter).to eq(voter)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should be callable with vote_down" do
|
48
|
+
votable.vote_down voter
|
49
|
+
expect(votable.get_down_votes.first.voter).to eq(voter)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should have 2 votes_for when voted on once by two different people" do
|
53
|
+
votable.vote_by voter: voter
|
54
|
+
votable.vote_by voter: voter2
|
55
|
+
expect(votable.votes_for.size).to eq(2)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should have one true vote" do
|
59
|
+
votable.vote_by voter: voter
|
60
|
+
votable.vote_by voter: voter2, vote: "dislike"
|
61
|
+
expect(votable.get_up_votes.size).to eq(1)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should have 2 false votes_for" do
|
65
|
+
votable.vote_by voter: voter, vote: "no"
|
66
|
+
votable.vote_by voter: voter2, vote: "dislike"
|
67
|
+
expect(votable.get_down_votes.size).to eq(2)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should have been voted on by voter2" do
|
71
|
+
votable.vote_by voter: voter2, vote: true
|
72
|
+
expect(votable.find_votes_for.first.voter.id).to be voter2.id
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should count the vote as registered if this is the voters first vote" do
|
76
|
+
votable.vote_by voter: voter
|
77
|
+
expect(votable.vote_registered?).to be true
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should not count the vote as being registered if that voter has already voted and the vote has not changed" do
|
81
|
+
votable.vote_by voter: voter, vote: true
|
82
|
+
votable.vote_by voter: voter, vote: "yes"
|
83
|
+
expect(votable.vote_registered?).to be false
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should count the vote as registered if the voter has voted and the vote flag has changed" do
|
87
|
+
votable.vote_by voter: voter, vote: true
|
88
|
+
votable.vote_by voter: voter, vote: "dislike"
|
89
|
+
expect(votable.vote_registered?).to be true
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should count the vote as registered if the voter has voted and the vote weight has changed" do
|
93
|
+
votable.vote_by voter: voter, vote: true, vote_weight: 1
|
94
|
+
votable.vote_by voter: voter, vote: true, vote_weight: 2
|
95
|
+
expect(votable.vote_registered?).to be true
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should be voted on by voter" do
|
99
|
+
votable.vote_by voter: voter
|
100
|
+
expect(votable.voted_on_by?(voter)).to be true
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should be able to unvote a voter" do
|
104
|
+
votable.liked_by(voter)
|
105
|
+
votable.unliked_by(voter)
|
106
|
+
expect(votable.voted_on_by?(voter)).to be false
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should unvote a positive vote" do
|
110
|
+
votable.vote_by voter: voter
|
111
|
+
votable.unvote voter: voter
|
112
|
+
expect(votable.find_votes_for.count).to eq(0)
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should set the votable to unregistered after unvoting" do
|
116
|
+
votable.vote_by voter: voter
|
117
|
+
votable.unvote voter: voter
|
118
|
+
expect(votable.vote_registered?).to be false
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should unvote a negative vote" do
|
122
|
+
votable.vote_by voter: voter, vote: "no"
|
123
|
+
votable.unvote voter: voter
|
124
|
+
expect(votable.find_votes_for.count).to eq(0)
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should unvote only the from a single voter" do
|
128
|
+
votable.vote_by voter: voter
|
129
|
+
votable.vote_by voter: voter2
|
130
|
+
votable.unvote voter: voter
|
131
|
+
expect(votable.find_votes_for.count).to eq(1)
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should be contained to instances" do
|
135
|
+
votable2 = build(:votable, name: "2nd votable")
|
136
|
+
votable2.save
|
137
|
+
|
138
|
+
votable.vote_by voter: voter, vote: false
|
139
|
+
votable2.vote_by voter: voter, vote: true
|
140
|
+
votable2.vote_by voter: voter, vote: true
|
141
|
+
|
142
|
+
expect(votable.vote_registered?).to be true
|
143
|
+
expect(votable2.vote_registered?).to be false
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should set default vote weight to 1 if not specified" do
|
147
|
+
votable.upvote_by voter
|
148
|
+
expect(votable.find_votes_for.first.vote_weight).to eq(1)
|
149
|
+
end
|
150
|
+
|
151
|
+
describe "with cached votes_for" do
|
152
|
+
let!(:voter) { create(:voter, name: "i can vote!") }
|
153
|
+
let!(:votable) { create(:votable, name: "a voting model without a cache") }
|
154
|
+
let!(:votable_cache) { create(:votable_cache, name: "voting model with cache") }
|
155
|
+
|
156
|
+
it "should not update cached votes_for if there are no columns" do
|
157
|
+
votable.vote_by voter: voter
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should update cached total votes_for if there is a total column" do
|
161
|
+
votable_cache.cached_votes_total = 50
|
162
|
+
votable_cache.vote_by voter: voter
|
163
|
+
expect(votable_cache.cached_votes_total).to eq(1)
|
164
|
+
end
|
165
|
+
|
166
|
+
it "should update cached total votes_for when a vote up is removed" do
|
167
|
+
votable_cache.vote_by voter: voter, vote: "true"
|
168
|
+
votable_cache.unvote voter: voter
|
169
|
+
expect(votable_cache.cached_votes_total).to eq(0)
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should update cached total votes_for when a vote down is removed" do
|
173
|
+
votable_cache.vote_by voter: voter, vote: "false"
|
174
|
+
votable_cache.unvote voter: voter
|
175
|
+
expect(votable_cache.cached_votes_total).to eq(0)
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should update cached score votes_for if there is a score column" do
|
179
|
+
votable_cache.cached_votes_score = 50
|
180
|
+
votable_cache.vote_by voter: voter
|
181
|
+
expect(votable_cache.cached_votes_score).to eq(1)
|
182
|
+
votable_cache.vote_by voter: voter2, vote: "false"
|
183
|
+
expect(votable_cache.cached_votes_score).to eq(0)
|
184
|
+
votable_cache.vote_by voter: voter, vote: "false"
|
185
|
+
expect(votable_cache.cached_votes_score).to eq(-2)
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should update cached score votes_for when a vote up is removed" do
|
189
|
+
votable_cache.vote_by voter: voter, vote: "true"
|
190
|
+
expect(votable_cache.cached_votes_score).to eq(1)
|
191
|
+
votable_cache.unvote voter: voter
|
192
|
+
expect(votable_cache.cached_votes_score).to eq(0)
|
193
|
+
end
|
194
|
+
|
195
|
+
it "should update cached score votes_for when a vote down is removed" do
|
196
|
+
votable_cache.vote_by voter: voter, vote: "false"
|
197
|
+
expect(votable_cache.cached_votes_score).to eq(-1)
|
198
|
+
votable_cache.unvote voter: voter
|
199
|
+
expect(votable_cache.cached_votes_score).to eq(0)
|
200
|
+
end
|
201
|
+
|
202
|
+
it "should update cached weighted total if there is a weighted total column" do
|
203
|
+
votable_cache.cached_weighted_total = 50
|
204
|
+
votable_cache.vote_by voter: voter
|
205
|
+
expect(votable_cache.cached_weighted_total).to eq(1)
|
206
|
+
votable_cache.vote_by voter: voter2, vote: "false"
|
207
|
+
expect(votable_cache.cached_weighted_total).to eq(2)
|
208
|
+
end
|
209
|
+
|
210
|
+
it "should update cached weighted total votes_for when a vote up is removed" do
|
211
|
+
votable_cache.vote_by voter: voter, vote: "true", vote_weight: 3
|
212
|
+
expect(votable_cache.cached_weighted_total).to eq(3)
|
213
|
+
votable_cache.unvote voter: voter
|
214
|
+
expect(votable_cache.cached_weighted_total).to eq(0)
|
215
|
+
end
|
216
|
+
|
217
|
+
it "should update cached weighted total votes_for when a vote down is removed" do
|
218
|
+
votable_cache.vote_by voter: voter, vote: "false", vote_weight: 4
|
219
|
+
expect(votable_cache.cached_weighted_total).to eq(4)
|
220
|
+
votable_cache.unvote voter: voter
|
221
|
+
expect(votable_cache.cached_weighted_total).to eq(0)
|
222
|
+
end
|
223
|
+
|
224
|
+
it "should update cached weighted score if there is a weighted score column" do
|
225
|
+
votable_cache.cached_weighted_score = 50
|
226
|
+
votable_cache.vote_by voter: voter, vote_weight: 3
|
227
|
+
expect(votable_cache.cached_weighted_score).to eq(3)
|
228
|
+
votable_cache.vote_by voter: voter2, vote: "false", vote_weight: 5
|
229
|
+
expect(votable_cache.cached_weighted_score).to eq(-2)
|
230
|
+
# voter changes her vote from 3 to 5
|
231
|
+
votable_cache.vote_by voter: voter, vote_weight: 5
|
232
|
+
expect(votable_cache.cached_weighted_score).to eq(0)
|
233
|
+
votable_cache.vote_by voter: voter3, vote_weight: 4
|
234
|
+
expect(votable_cache.cached_weighted_score).to eq(4)
|
235
|
+
end
|
236
|
+
|
237
|
+
it "should update cached weighted score votes_for when a vote up is removed" do
|
238
|
+
votable_cache.vote_by voter: voter, vote: "true", vote_weight: 3
|
239
|
+
expect(votable_cache.cached_weighted_score).to eq(3)
|
240
|
+
votable_cache.unvote voter: voter
|
241
|
+
expect(votable_cache.cached_weighted_score).to eq(0)
|
242
|
+
end
|
243
|
+
|
244
|
+
it "should update cached weighted score votes_for when a vote down is removed" do
|
245
|
+
votable_cache.vote_by voter: voter, vote: "false", vote_weight: 4
|
246
|
+
expect(votable_cache.cached_weighted_score).to eq(-4)
|
247
|
+
votable_cache.unvote voter: voter
|
248
|
+
expect(votable_cache.cached_weighted_score).to eq(0)
|
249
|
+
end
|
250
|
+
|
251
|
+
it "should update cached weighted average if there is a weighted average column" do
|
252
|
+
votable_cache.cached_weighted_average = 50.0
|
253
|
+
votable_cache.vote_by voter: voter, vote: "true", vote_weight: 5
|
254
|
+
expect(votable_cache.cached_weighted_average).to eq(5.0)
|
255
|
+
votable_cache.vote_by voter: voter2, vote: "true", vote_weight: 3
|
256
|
+
expect(votable_cache.cached_weighted_average).to eq(4.0)
|
257
|
+
# voter changes her vote from 5 to 4
|
258
|
+
votable_cache.vote_by voter: voter, vote: "true", vote_weight: 4
|
259
|
+
expect(votable_cache.cached_weighted_average).to eq(3.5)
|
260
|
+
votable_cache.vote_by voter: voter3, vote: "true", vote_weight: 5
|
261
|
+
expect(votable_cache.cached_weighted_average).to eq(4.0)
|
262
|
+
end
|
263
|
+
|
264
|
+
it "should update cached weighted average votes_for when a vote up is removed" do
|
265
|
+
votable_cache.vote_by voter: voter, vote: "true", vote_weight: 5
|
266
|
+
votable_cache.vote_by voter: voter2, vote: "true", vote_weight: 3
|
267
|
+
expect(votable_cache.cached_weighted_average).to eq(4)
|
268
|
+
votable_cache.unvote voter: voter
|
269
|
+
expect(votable_cache.cached_weighted_average).to eq(3)
|
270
|
+
end
|
271
|
+
|
272
|
+
it "should update cached up votes_for if there is an up vote column" do
|
273
|
+
votable_cache.cached_votes_up = 50
|
274
|
+
votable_cache.vote_by voter: voter
|
275
|
+
votable_cache.vote_by voter: voter
|
276
|
+
expect(votable_cache.cached_votes_up).to eq(1)
|
277
|
+
end
|
278
|
+
|
279
|
+
it "should update cached down votes_for if there is a down vote column" do
|
280
|
+
votable_cache.cached_votes_down = 50
|
281
|
+
votable_cache.vote_by voter: voter, vote: "false"
|
282
|
+
expect(votable_cache.cached_votes_down).to eq(1)
|
283
|
+
end
|
284
|
+
|
285
|
+
it "should update cached up votes_for when a vote up is removed" do
|
286
|
+
votable_cache.vote_by voter: voter, vote: "true"
|
287
|
+
votable_cache.unvote voter: voter
|
288
|
+
expect(votable_cache.cached_votes_up).to eq(0)
|
289
|
+
end
|
290
|
+
|
291
|
+
it "should update cached down votes_for when a vote down is removed" do
|
292
|
+
votable_cache.vote_by voter: voter, vote: "false"
|
293
|
+
votable_cache.unvote voter: voter
|
294
|
+
expect(votable_cache.cached_votes_down).to eq(0)
|
295
|
+
end
|
296
|
+
|
297
|
+
it "should select from cached total votes_for if there a total column" do
|
298
|
+
votable_cache.vote_by voter: voter
|
299
|
+
votable_cache.cached_votes_total = 50
|
300
|
+
expect(votable_cache.count_votes_total).to eq(50)
|
301
|
+
end
|
302
|
+
|
303
|
+
it "should select from cached up votes_for if there is an up vote column" do
|
304
|
+
votable_cache.vote_by voter: voter
|
305
|
+
votable_cache.cached_votes_up = 50
|
306
|
+
expect(votable_cache.count_votes_up).to eq(50)
|
307
|
+
end
|
308
|
+
|
309
|
+
it "should select from cached down votes_for if there is a down vote column" do
|
310
|
+
votable_cache.vote_by voter: voter, vote: "false"
|
311
|
+
votable_cache.cached_votes_down = 50
|
312
|
+
expect(votable_cache.count_votes_down).to eq(50)
|
313
|
+
end
|
314
|
+
|
315
|
+
it "should select from cached votes score if there is a votes score column" do
|
316
|
+
votable_cache.vote_by voter: voter, vote: "false"
|
317
|
+
votable_cache.cached_votes_score = 50
|
318
|
+
expect(votable_cache.count_votes_score).to eq(50)
|
319
|
+
end
|
320
|
+
|
321
|
+
it "should select from cached weighted total if there is a weighted total column" do
|
322
|
+
votable_cache.vote_by voter: voter, vote: "false"
|
323
|
+
votable_cache.cached_weighted_total = 50
|
324
|
+
expect(votable_cache.weighted_total).to eq(50)
|
325
|
+
end
|
326
|
+
|
327
|
+
it "should select from cached weighted score if there is a weighted score column" do
|
328
|
+
votable_cache.vote_by voter: voter, vote: "false"
|
329
|
+
votable_cache.cached_weighted_score = 50
|
330
|
+
expect(votable_cache.weighted_score).to eq(50)
|
331
|
+
end
|
332
|
+
|
333
|
+
it "should select from cached weighted average if there is a weighted average column" do
|
334
|
+
votable_cache.vote_by voter: voter, vote: "false"
|
335
|
+
votable_cache.cached_weighted_average = 50
|
336
|
+
expect(votable_cache.weighted_average).to eq(50)
|
337
|
+
end
|
338
|
+
|
339
|
+
it "should update cached total votes_for when voting under an scope" do
|
340
|
+
votable_cache.vote_by voter: voter, vote: "true", vote_scope: "rank"
|
341
|
+
expect(votable_cache.cached_votes_total).to eq(1)
|
342
|
+
end
|
343
|
+
|
344
|
+
it "should update cached up votes_for when voting under an scope" do
|
345
|
+
votable_cache.vote_by voter: voter, vote: "true", vote_scope: "rank"
|
346
|
+
expect(votable_cache.cached_votes_up).to eq(1)
|
347
|
+
end
|
348
|
+
|
349
|
+
it "should update cached total votes_for when a scoped vote down is removed" do
|
350
|
+
votable_cache.vote_by voter: voter, vote: "true", vote_scope: "rank"
|
351
|
+
votable_cache.unvote voter: voter, vote_scope: "rank"
|
352
|
+
expect(votable_cache.cached_votes_total).to eq(0)
|
353
|
+
end
|
354
|
+
|
355
|
+
it "should update cached up votes_for when a scoped vote down is removed" do
|
356
|
+
votable_cache.vote_by voter: voter, vote: "true", vote_scope: "rank"
|
357
|
+
votable_cache.unvote voter: voter, vote_scope: "rank"
|
358
|
+
expect(votable_cache.cached_votes_up).to eq(0)
|
359
|
+
end
|
360
|
+
|
361
|
+
it "should update cached down votes_for when downvoting under a scope" do
|
362
|
+
votable_cache.vote_by voter: voter, vote: "false", vote_scope: "rank"
|
363
|
+
expect(votable_cache.cached_votes_down).to eq(1)
|
364
|
+
end
|
365
|
+
|
366
|
+
it "should update cached down votes_for when a scoped vote down is removed" do
|
367
|
+
votable_cache.vote_by voter: voter, vote: "false", vote_scope: "rank"
|
368
|
+
votable_cache.unvote voter: voter, vote_scope: "rank"
|
369
|
+
expect(votable_cache.cached_votes_down).to eq(0)
|
370
|
+
end
|
371
|
+
|
372
|
+
describe "with acts_as_votable_options" do
|
373
|
+
describe "cacheable_strategy" do
|
374
|
+
let(:updated_at) { 3.days.ago }
|
375
|
+
|
376
|
+
before { votable_cache.vote_by voter: voter }
|
377
|
+
|
378
|
+
context "update_attributes" do
|
379
|
+
let(:votable_cache) { create(:votable_cache_update_attributes, name: "voting model with cache", updated_at: updated_at) }
|
380
|
+
|
381
|
+
it do
|
382
|
+
expect(votable_cache.cached_votes_total).to eq(1)
|
383
|
+
expect(votable_cache.updated_at).to_not eq updated_at
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
context "update_columns" do
|
388
|
+
let(:votable_cache) { create(:votable_cache_update_columns, name: "voting model with cache", updated_at: updated_at) }
|
389
|
+
|
390
|
+
it do
|
391
|
+
expect(votable_cache.cached_votes_total).to eq(1)
|
392
|
+
expect(votable_cache.updated_at).to eq updated_at
|
393
|
+
end
|
394
|
+
end
|
395
|
+
end
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
describe "with scoped cached votes_for" do
|
400
|
+
|
401
|
+
it "should update cached total votes_for if there is a total column" do
|
402
|
+
votable_cache.cached_scoped_test_votes_total = 50
|
403
|
+
votable_cache.vote_by voter: voter, vote_scope: "test"
|
404
|
+
expect(votable_cache.cached_scoped_test_votes_total).to eq(1)
|
405
|
+
end
|
406
|
+
|
407
|
+
it "should update cached total votes_for when a vote up is removed" do
|
408
|
+
votable_cache.vote_by voter: voter, vote: "true", vote_scope: "test"
|
409
|
+
votable_cache.unvote voter: voter, vote_scope: "test"
|
410
|
+
expect(votable_cache.cached_scoped_test_votes_total).to eq(0)
|
411
|
+
end
|
412
|
+
|
413
|
+
it "should update cached total votes_for when a vote down is removed" do
|
414
|
+
votable_cache.vote_by voter: voter, vote: "false", vote_scope: "test"
|
415
|
+
votable_cache.unvote voter: voter, vote_scope: "test"
|
416
|
+
expect(votable_cache.cached_scoped_test_votes_total).to eq(0)
|
417
|
+
end
|
418
|
+
|
419
|
+
it "should update cached score votes_for if there is a score column" do
|
420
|
+
votable_cache.cached_scoped_test_votes_score = 50
|
421
|
+
votable_cache.vote_by voter: voter, vote_scope: "test"
|
422
|
+
expect(votable_cache.cached_scoped_test_votes_score).to eq(1)
|
423
|
+
votable_cache.vote_by voter: voter2, vote: "false", vote_scope: "test"
|
424
|
+
expect(votable_cache.cached_scoped_test_votes_score).to eq(0)
|
425
|
+
votable_cache.vote_by voter: voter, vote: "false", vote_scope: "test"
|
426
|
+
expect(votable_cache.cached_scoped_test_votes_score).to eq(-2)
|
427
|
+
end
|
428
|
+
|
429
|
+
it "should update cached score votes_for when a vote up is removed" do
|
430
|
+
votable_cache.vote_by voter: voter, vote: "true", vote_scope: "test"
|
431
|
+
expect(votable_cache.cached_scoped_test_votes_score).to eq(1)
|
432
|
+
votable_cache.unvote voter: voter, vote_scope: "test"
|
433
|
+
expect(votable_cache.cached_scoped_test_votes_score).to eq(0)
|
434
|
+
end
|
435
|
+
|
436
|
+
it "should update cached score votes_for when a vote down is removed" do
|
437
|
+
votable_cache.vote_by voter: voter, vote: "false", vote_scope: "test"
|
438
|
+
expect(votable_cache.cached_scoped_test_votes_score).to eq(-1)
|
439
|
+
votable_cache.unvote voter: voter, vote_scope: "test"
|
440
|
+
expect(votable_cache.cached_scoped_test_votes_score).to eq(0)
|
441
|
+
end
|
442
|
+
|
443
|
+
it "should update cached up votes_for if there is an up vote column" do
|
444
|
+
votable_cache.cached_scoped_test_votes_up = 50
|
445
|
+
votable_cache.vote_by voter: voter, vote_scope: "test"
|
446
|
+
votable_cache.vote_by voter: voter, vote_scope: "test"
|
447
|
+
expect(votable_cache.cached_scoped_test_votes_up).to eq(1)
|
448
|
+
end
|
449
|
+
|
450
|
+
it "should update cached down votes_for if there is a down vote column" do
|
451
|
+
votable_cache.cached_scoped_test_votes_down = 50
|
452
|
+
votable_cache.vote_by voter: voter, vote: "false", vote_scope: "test"
|
453
|
+
expect(votable_cache.cached_scoped_test_votes_down).to eq(1)
|
454
|
+
end
|
455
|
+
|
456
|
+
it "should update cached up votes_for when a vote up is removed" do
|
457
|
+
votable_cache.vote_by voter: voter, vote: "true", vote_scope: "test"
|
458
|
+
votable_cache.unvote voter: voter, vote_scope: "test"
|
459
|
+
expect(votable_cache.cached_scoped_test_votes_up).to eq(0)
|
460
|
+
end
|
461
|
+
|
462
|
+
it "should update cached down votes_for when a vote down is removed" do
|
463
|
+
votable_cache.vote_by voter: voter, vote: "false", vote_scope: "test"
|
464
|
+
votable_cache.unvote voter: voter, vote_scope: "test"
|
465
|
+
expect(votable_cache.cached_scoped_test_votes_down).to eq(0)
|
466
|
+
end
|
467
|
+
|
468
|
+
it "should select from cached total votes_for if there a total column" do
|
469
|
+
votable_cache.vote_by voter: voter, vote_scope: "test"
|
470
|
+
votable_cache.cached_scoped_test_votes_total = 50
|
471
|
+
expect(votable_cache.count_votes_total(false, "test")).to eq(50)
|
472
|
+
end
|
473
|
+
|
474
|
+
it "should select from cached up votes_for if there is an up vote column" do
|
475
|
+
votable_cache.vote_by voter: voter, vote_scope: "test"
|
476
|
+
votable_cache.cached_scoped_test_votes_up = 50
|
477
|
+
expect(votable_cache.count_votes_up(false, "test")).to eq(50)
|
478
|
+
end
|
479
|
+
|
480
|
+
it "should select from cached down votes_for if there is a down vote column" do
|
481
|
+
votable_cache.vote_by voter: voter, vote: "false", vote_scope: "test"
|
482
|
+
votable_cache.cached_scoped_test_votes_down = 50
|
483
|
+
expect(votable_cache.count_votes_down(false, "test")).to eq(50)
|
484
|
+
end
|
485
|
+
|
486
|
+
end
|
487
|
+
|
488
|
+
describe "sti models" do
|
489
|
+
let(:child_sti_not_votable) { create(:child_of_sti_not_votable, name: "sti child") }
|
490
|
+
let(:child_sti_votable) { create(:child_of_sti_votable, name: "sti child") }
|
491
|
+
|
492
|
+
it "should be able to vote on a votable child of a non votable sti model" do
|
493
|
+
child_sti_not_votable.vote_by voter: voter, vote: "yes"
|
494
|
+
expect(child_sti_not_votable.votes_for.size).to eq(1)
|
495
|
+
end
|
496
|
+
|
497
|
+
it "should not be able to vote on a parent non votable" do
|
498
|
+
expect(StiNotVotable).not_to be_votable
|
499
|
+
end
|
500
|
+
|
501
|
+
it "should be able to vote on a child when its parent is votable" do
|
502
|
+
child_sti_votable.vote_by voter: voter, vote: "yes"
|
503
|
+
expect(child_sti_votable.votes_for.size).to eq(1)
|
504
|
+
end
|
505
|
+
end
|
506
|
+
end
|