acts_as_votable 0.5.0 → 0.9.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.
@@ -6,13 +6,13 @@ module ActsAsVotable
6
6
  include Helpers::Words
7
7
 
8
8
  def self.included base
9
-
10
- # allow the user to define these himself
9
+
10
+ # allow the user to define these himself
11
11
  aliases = {
12
12
 
13
13
  :vote_up => [
14
- :up_by, :upvote_by, :like_by, :liked_by, :vote_by,
15
- :up_from, :upvote_from, :upvote_by, :like_from, :liked_from, :vote_from
14
+ :up_by, :upvote_by, :like_by, :liked_by,
15
+ :up_from, :upvote_from, :upvote_by, :like_from, :liked_from, :vote_from
16
16
  ],
17
17
 
18
18
  :vote_down => [
@@ -20,22 +20,20 @@ module ActsAsVotable
20
20
  :down_from, :downvote_from, :downvote_by, :dislike_by, :disliked_by
21
21
  ],
22
22
 
23
- :up_votes => [
24
- :true_votes, :ups, :upvotes, :likes, :positives, :for_votes,
23
+ :get_up_votes => [
24
+ :get_true_votes, :get_ups, :get_upvotes, :get_likes, :get_positives, :get_for_votes,
25
25
  ],
26
26
 
27
- :down_votes => [
28
- :false_votes, :downs, :downvotes, :dislikes, :negatives
27
+ :get_down_votes => [
28
+ :get_false_votes, :get_downs, :get_downvotes, :get_dislikes, :get_negatives
29
29
  ],
30
- :unvote => [
31
- :unliked_by, :undisliked_by
30
+ :unvote_by => [
31
+ :unvote_up, :unvote_down, :unliked_by, :undisliked_by
32
32
  ]
33
33
  }
34
34
 
35
35
  base.class_eval do
36
-
37
- belongs_to :votable, :polymorphic => true
38
- has_many :votes, :class_name => "ActsAsVotable::Vote", :as => :votable do
36
+ has_many :votes_for, :class_name => 'ActsAsVotable::Vote', :as => :votable, :dependent => :destroy do
39
37
  def voters
40
38
  includes(:voter).map(&:voter)
41
39
  end
@@ -64,7 +62,7 @@ module ActsAsVotable
64
62
  end
65
63
 
66
64
  # voting
67
- def vote args = {}
65
+ def vote_by args = {}
68
66
 
69
67
  options = {
70
68
  :vote => true,
@@ -78,13 +76,13 @@ module ActsAsVotable
78
76
  end
79
77
 
80
78
  # find the vote
81
- _votes_ = find_votes({
79
+ _votes_ = find_votes_for({
82
80
  :voter_id => options[:voter].id,
83
81
  :vote_scope => options[:vote_scope],
84
82
  :voter_type => options[:voter].class.name
85
83
  })
86
84
 
87
- if _votes_.count == 0
85
+ if _votes_.count == 0 or options[:duplicate]
88
86
  # this voter has never voted
89
87
  vote = ActsAsVotable::Vote.new(
90
88
  :votable => self,
@@ -93,16 +91,19 @@ module ActsAsVotable
93
91
  )
94
92
  else
95
93
  # this voter is potentially changing his vote
96
- vote = _votes_.first
94
+ vote = _votes_.last
97
95
  end
98
96
 
99
97
  last_update = vote.updated_at
100
98
 
101
99
  vote.vote_flag = votable_words.meaning_of(options[:vote])
102
100
 
101
+ #Allowing for a vote_weight to be associated with every vote. Could change with every voter object
102
+ vote.vote_weight = (options[:vote_weight].to_i if options[:vote_weight].present?) || 1
103
+
103
104
  if vote.save
104
105
  self.vote_registered = true if last_update != vote.updated_at
105
- update_cached_votes
106
+ update_cached_votes options[:vote_scope]
106
107
  return true
107
108
  else
108
109
  self.vote_registered = false
@@ -113,25 +114,56 @@ module ActsAsVotable
113
114
 
114
115
  def unvote args = {}
115
116
  return false if args[:voter].nil?
116
- _votes_ = find_votes(:voter_id => args[:voter].id, :vote_scope => args[:vote_scope], :voter_type => args[:voter].class.name)
117
+ _votes_ = find_votes_for(:voter_id => args[:voter].id, :vote_scope => args[:vote_scope], :voter_type => args[:voter].class.name)
117
118
 
118
119
  return true if _votes_.size == 0
119
120
  _votes_.each(&:destroy)
120
- update_cached_votes
121
- self.vote_registered = false if votes.count == 0
121
+ update_cached_votes args[:vote_scope]
122
+ self.vote_registered = false if votes_for.count == 0
122
123
  return true
123
124
  end
124
125
 
125
126
  def vote_up voter, options={}
126
- self.vote :voter => voter, :vote => true, :vote_scope => options[:vote_scope]
127
+ self.vote_by :voter => voter, :vote => true, :vote_scope => options[:vote_scope], :vote_weight => options[:vote_weight]
127
128
  end
128
129
 
129
130
  def vote_down voter, options={}
130
- self.vote :voter => voter, :vote => false, :vote_scope => options[:vote_scope]
131
+ self.vote_by :voter => voter, :vote => false, :vote_scope => options[:vote_scope], :vote_weight => options[:vote_weight]
132
+ end
133
+
134
+ def unvote_by voter, options = {}
135
+ self.unvote :voter => voter, :vote_scope => options[:vote_scope] #Does not need vote_weight since the votes_for are anyway getting destroyed
136
+ end
137
+
138
+ def scope_cache_field field, vote_scope
139
+ return field if vote_scope.nil?
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_score
159
+ "cached_weighted_#{vote_scope}_score"
160
+ when :cached_weighted_score=
161
+ "cached_weighted_#{vote_scope}_score="
162
+ end
131
163
  end
132
164
 
133
165
  # caching
134
- def update_cached_votes
166
+ def update_cached_votes vote_scope = nil
135
167
 
136
168
  updates = {}
137
169
 
@@ -154,50 +186,92 @@ module ActsAsVotable
154
186
  )
155
187
  end
156
188
 
157
- self.update_attributes(updates, :without_protection => true) if updates.size > 0
189
+ if self.respond_to?(:cached_weighted_score=)
190
+ updates[:cached_weighted_score] = weighted_score(true)
191
+ end
192
+
193
+ if vote_scope
194
+ if self.respond_to?(scope_cache_field :cached_votes_total=, vote_scope)
195
+ updates[scope_cache_field :cached_votes_total, vote_scope] = count_votes_total(true, vote_scope)
196
+ end
197
+
198
+ if self.respond_to?(scope_cache_field :cached_votes_up=, vote_scope)
199
+ updates[scope_cache_field :cached_votes_up, vote_scope] = count_votes_up(true, vote_scope)
200
+ end
201
+
202
+ if self.respond_to?(scope_cache_field :cached_votes_down=, vote_scope)
203
+ updates[scope_cache_field :cached_votes_down, vote_scope] = count_votes_down(true, vote_scope)
204
+ end
205
+
206
+ if self.respond_to?(scope_cache_field :cached_weighted_score=, vote_scope)
207
+ updates[scope_cache_field :cached_weighted_score, vote_scope] = weighted_score(true, vote_scope)
208
+ end
209
+
210
+ if self.respond_to?(scope_cache_field :cached_votes_score=, vote_scope)
211
+ updates[scope_cache_field :cached_votes_score, vote_scope] = (
212
+ (updates[scope_cache_field :cached_votes_up, vote_scope] || count_votes_up(true, vote_scope)) -
213
+ (updates[scope_cache_field :cached_votes_down, vote_scope] || count_votes_down(true, vote_scope))
214
+ )
215
+ end
216
+ end
217
+
218
+ if (::ActiveRecord::VERSION::MAJOR == 3) && (::ActiveRecord::VERSION::MINOR != 0)
219
+ self.update_attributes(updates, :without_protection => true) if updates.size > 0
220
+ else
221
+ self.update_attributes(updates) if updates.size > 0
222
+ end
158
223
 
159
224
  end
160
225
 
161
226
 
162
227
  # results
163
- def find_votes extra_conditions = {}
164
- votes.where(extra_conditions)
228
+ def find_votes_for extra_conditions = {}
229
+ votes_for.where(extra_conditions)
165
230
  end
166
231
 
167
- def up_votes options={}
168
- find_votes(:vote_flag => true, :vote_scope => options[:vote_scope])
232
+ def get_up_votes options={}
233
+ find_votes_for(:vote_flag => true, :vote_scope => options[:vote_scope])
169
234
  end
170
235
 
171
- def down_votes options={}
172
- find_votes(:vote_flag => false, :vote_scope => options[:vote_scope])
236
+ def get_down_votes options={}
237
+ find_votes_for(:vote_flag => false, :vote_scope => options[:vote_scope])
173
238
  end
174
239
 
175
240
 
176
241
  # counting
177
- def count_votes_total skip_cache = false
178
- if !skip_cache && self.respond_to?(:cached_votes_total)
179
- return self.send(:cached_votes_total)
242
+ def count_votes_total skip_cache = false, vote_scope = nil
243
+ if !skip_cache && self.respond_to?(scope_cache_field :cached_votes_total, vote_scope)
244
+ return self.send(scope_cache_field :cached_votes_total, vote_scope)
245
+ end
246
+ find_votes_for(:vote_scope => vote_scope).count
247
+ end
248
+
249
+ def count_votes_up skip_cache = false, vote_scope = nil
250
+ if !skip_cache && self.respond_to?(scope_cache_field :cached_votes_up, vote_scope)
251
+ return self.send(scope_cache_field :cached_votes_up, vote_scope)
180
252
  end
181
- find_votes.count
253
+ get_up_votes(:vote_scope => vote_scope).count
182
254
  end
183
255
 
184
- def count_votes_up skip_cache = false
185
- if !skip_cache && self.respond_to?(:cached_votes_up)
186
- return self.send(:cached_votes_up)
256
+ def count_votes_down skip_cache = false, vote_scope = nil
257
+ if !skip_cache && self.respond_to?(scope_cache_field :cached_votes_down, vote_scope)
258
+ return self.send(scope_cache_field :cached_votes_down, vote_scope)
187
259
  end
188
- up_votes.count
260
+ get_down_votes(:vote_scope => vote_scope).count
189
261
  end
190
262
 
191
- def count_votes_down skip_cache = false
192
- if !skip_cache && self.respond_to?(:cached_votes_down)
193
- return self.send(:cached_votes_down)
263
+ def weighted_score skip_cache = false, vote_scope = nil
264
+ if !skip_cache && self.respond_to?(scope_cache_field :cached_weighted_score, vote_scope)
265
+ return self.send(scope_cache_field :cached_weighted_score, vote_scope)
194
266
  end
195
- down_votes.count
267
+ ups = get_up_votes(:vote_scope => vote_scope).sum(:vote_weight)
268
+ downs = get_down_votes(:vote_scope => vote_scope).sum(:vote_weight)
269
+ ups - downs
196
270
  end
197
271
 
198
272
  # voters
199
273
  def voted_on_by? voter
200
- votes = find_votes :voter_id => voter.id, :voter_type => voter.class.name
274
+ votes = find_votes_for :voter_id => voter.id, :voter_type => voter.class.name
201
275
  votes.count > 0
202
276
  end
203
277
 
@@ -5,16 +5,18 @@ module ActsAsVotable
5
5
 
6
6
  include Helpers::Words
7
7
 
8
- attr_accessible :votable_id, :votable_type,
9
- :voter_id, :voter_type,
10
- :votable, :voter,
11
- :vote_flag, :vote_scope
8
+ if ::ActiveRecord::VERSION::MAJOR < 4
9
+ attr_accessible :votable_id, :votable_type,
10
+ :voter_id, :voter_type,
11
+ :votable, :voter,
12
+ :vote_flag, :vote_scope
13
+ end
12
14
 
13
15
  belongs_to :votable, :polymorphic => true
14
16
  belongs_to :voter, :polymorphic => true
15
17
 
16
- scope :up, where(:vote_flag => true)
17
- scope :down, where(:vote_flag => false)
18
+ scope :up, lambda{ where(:vote_flag => true) }
19
+ scope :down, lambda{ where(:vote_flag => false) }
18
20
  scope :for_type, lambda{ |klass| where(:votable_type => klass) }
19
21
  scope :by_type, lambda{ |klass| where(:voter_type => klass) }
20
22
 
@@ -5,17 +5,20 @@ module ActsAsVotable
5
5
 
6
6
  # allow user to define these
7
7
  aliases = {
8
- :vote_up_for => [:likes, :upvotes, :up_votes],
9
- :vote_down_for => [:dislikes, :downvotes, :down_votes],
10
- :unvote_for => [:unlike, :undislike],
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?],
11
12
  :voted_up_on? => [:voted_up_for?, :liked?],
12
- :voted_down_on? => [:voted_down_for?, :disliked?]
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]
13
17
  }
14
18
 
15
19
  base.class_eval do
16
20
 
17
- belongs_to :voter, :polymorphic => true
18
- has_many :votes, :class_name => "ActsAsVotable::Vote", :as => :voter do
21
+ has_many :votes, :class_name => 'ActsAsVotable::Vote', :as => :voter, :dependent => :destroy do
19
22
  def votables
20
23
  includes(:votable).map(&:votable)
21
24
  end
@@ -33,7 +36,7 @@ module ActsAsVotable
33
36
 
34
37
  # voting
35
38
  def vote args
36
- args[:votable].vote args.merge({:voter => self})
39
+ args[:votable].vote_by args.merge({:voter => self})
37
40
  end
38
41
 
39
42
  def vote_up_for model=nil, args={}
@@ -44,8 +47,8 @@ module ActsAsVotable
44
47
  vote :votable => model, :vote_scope => args[:vote_scope], :vote => false
45
48
  end
46
49
 
47
- def unvote_for model
48
- model.unvote :voter => self
50
+ def unvote_for model, args={}
51
+ model.unvote :voter => self, :vote_scope => args[:vote_scope]
49
52
  end
50
53
 
51
54
  # results
@@ -66,15 +69,13 @@ module ActsAsVotable
66
69
  :vote_scope => args[:vote_scope], :vote_flag => false)
67
70
  votes.size > 0
68
71
  end
69
- alias :voted_down_for? :voted_down_on?
70
72
 
71
73
  def voted_as_when_voting_on votable, args={}
72
- votes = find_votes(:votable_id => votable.id, :votable_type => votable.class.name,
73
- :vote_scope => args[:vote_scope])
74
- return nil if votes.size == 0
75
- return votes.first.vote_flag
74
+ vote = find_votes(:votable_id => votable.id, :votable_type => votable.class.name,
75
+ :vote_scope => args[:vote_scope]).select(:vote_flag).last
76
+ return nil unless vote
77
+ return vote.vote_flag
76
78
  end
77
- alias :voted_as_when_voted_for :voted_as_when_voting_on
78
79
 
79
80
  def find_votes extra_conditions = {}
80
81
  votes.where(extra_conditions)
@@ -113,23 +114,21 @@ module ActsAsVotable
113
114
  def find_up_voted_items extra_conditions = {}
114
115
  find_voted_items extra_conditions.merge(:vote_flag => true)
115
116
  end
116
- alias_method :find_liked_items, :find_up_voted_items
117
117
 
118
118
  def find_down_voted_items extra_conditions = {}
119
119
  find_voted_items extra_conditions.merge(:vote_flag => false)
120
120
  end
121
- alias_method :find_disliked_items, :find_down_voted_items
122
121
 
123
122
  def get_voted klass, extra_conditions = {}
124
- klass.joins(:votes).merge find_votes(extra_conditions)
123
+ klass.joins(:votes_for).merge find_votes(extra_conditions)
125
124
  end
126
125
 
127
126
  def get_up_voted klass
128
- klass.joins(:votes).merge find_up_votes
127
+ klass.joins(:votes_for).merge find_up_votes
129
128
  end
130
129
 
131
130
  def get_down_voted klass
132
- klass.joins(:votes).merge find_down_votes
131
+ klass.joins(:votes_for).merge find_down_votes
133
132
  end
134
133
  end
135
134
  end
@@ -14,3 +14,8 @@ module ActsAsVotable
14
14
  end
15
15
 
16
16
  end
17
+
18
+ require 'acts_as_votable/extenders/controller'
19
+ ActiveSupport.on_load(:action_controller) do
20
+ include ActsAsVotable::Extenders::Controller
21
+ end
@@ -24,8 +24,8 @@ module ActsAsVotable
24
24
 
25
25
  def create_migration_file
26
26
  if self.class.orm_has_migration?
27
- migration_template 'migration.rb', 'db/migrate/acts_as_votable_migration'
27
+ migration_template 'migration.rb', 'db/migrate/acts_as_votable_migration.rb'
28
28
  end
29
29
  end
30
30
  end
31
- end
31
+ end
@@ -7,12 +7,16 @@ class ActsAsVotableMigration < ActiveRecord::Migration
7
7
 
8
8
  t.boolean :vote_flag
9
9
  t.string :vote_scope
10
+ t.integer :vote_weight
10
11
 
11
12
  t.timestamps
12
13
  end
13
14
 
14
- add_index :votes, [:votable_id, :votable_type]
15
- add_index :votes, [:voter_id, :voter_type]
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
+
16
20
  add_index :votes, [:voter_id, :voter_type, :vote_scope]
17
21
  add_index :votes, [:votable_id, :votable_type, :vote_scope]
18
22
  end