Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

remake_stats; Better code oganization

  • Loading branch information...
commit 0cb86aeb553310af52ea96c0d7315a28fb234e02 1 parent 9f3af8b
@tiendung tiendung authored
View
3  .watchr
@@ -19,6 +19,5 @@ end
watch("lib/(.*/.*)\.rb") do |match|
puts(match[1])
- spec("spec/unit/#{match[1]}_spec.rb")
- spec("spec/functional/#{match[1]}_spec.rb")
+ spec("spec/#{match[1]}_spec.rb")
end
View
6 lib/voteable_mongoid.rb
@@ -1,2 +1,4 @@
-require 'mongoid/voteable'
-require 'mongoid/voter'
+require 'voteable_mongoid/voteable/stats'
+require 'voteable_mongoid/voteable'
+require 'voteable_mongoid/voter'
+
View
10 lib/voteable_mongoid/railties/database.rake
@@ -0,0 +1,10 @@
+namespace :db do
+ namespace :mongoid do
+ namespace :voteable do
+ desc 'Update up_votes_count, down_votes_count, votes_count and votes_point'
+ task :remake_stats => :environment do
+ Mongoid::Voteable::Stats.remake_stats
+ end
+ end
+ end
+end
View
65 lib/mongoid/voteable.rb → lib/voteable_mongoid/voteable.rb
@@ -3,21 +3,23 @@ module Voteable
extend ActiveSupport::Concern
# How many points should be assigned for each up or down vote.
- # This hash should be accessed and manipulated using Voteable.vote_point method
+ # This hash should manipulated using Voteable.vote_point method
VOTE_POINT = {}
included do
- index 'voteable.up_votes_count'
- index 'voteable.down_votes_count'
- index 'voteable.votes_count'
- index 'voteable.votes_point'
-
- scope :most_up_voted, order_by(['voteable.up_votes_count', :desc])
- scope :most_down_voted, order_by(['voteable.down_votes_count', :desc])
- scope :most_voted, order_by(['voteable.votes_count', :desc])
- scope :best_voted, order_by(['voteable.votes_point', :desc])
+ include Mongoid::Voteable::Stats
+ def self.voteable_related
+ foreign_keys = relations.values.map{ |meta| meta.try(:foreign_key) }.compact
+ only(foreign_keys + %w[voteable])
+ end
+
# Set vote point for each up (down) vote on an object of this class
+ #
+ # @param [Hash] options a hash containings:
+ #
+ # vote_point self, :up => +1, :down => -3
+ # vote_point Post, :up => +2, :down => -1, :update_counters => false
def self.vote_point(klass = self, options = nil)
VOTE_POINT[self.name] ||= {}
VOTE_POINT[self.name][klass.name] ||= options
@@ -147,29 +149,29 @@ def self.vote(options)
VOTE_POINT[klass].each do |class_name, value_point|
# For other class in VOTE_POINT options, if is parent of current class
next unless relation_metadata = relations[class_name.underscore]
- votee ||= options[:votee] || find(options[:votee_id])
+ next unless votee ||= options[:votee] || voteable_related.where(:id => options[:votee_id]).first
# If can find current votee foreign_key value for that class
- next unless foreign_key_value = votee.read_attribute(relation_metadata.foreign_key.to_sym)
+ next unless foreign_key_value = votee.read_attribute(relation_metadata.foreign_key)
- # Update that class / collection
inc_options = {}
+
if options[:revote]
if value == :up
inc_options['voteable.votes_point'] = value_point[:up] - value_point[:down]
- unless value_point[:not_increase_votes_count]
+ unless value_point[:update_counters] == false
inc_options['voteable.up_votes_count'] = +1
inc_options['voteable.down_votes_count'] = -1
end
else
inc_options['voteable.votes_point'] = -value_point[:up] + value_point[:down]
- unless value_point[:not_increase_votes_count]
+ unless value_point[:update_counters] == false
inc_options['voteable.up_votes_count'] = -1
inc_options['voteable.down_votes_count'] = +1
end
end
elsif options[:unvote]
inc_options['voteable.votes_point'] = -value_point[value]
- unless value_point[:not_increase_votes_count]
+ unless value_point[:update_counters] == false
inc_options['voteable.votes_count'] = -1
if value == :up
inc_options['voteable.up_votes_count'] = -1
@@ -179,7 +181,7 @@ def self.vote(options)
end
else # new vote
inc_options['voteable.votes_point'] = value_point[value]
- unless value_point[:not_increase_votes_count]
+ unless value_point[:update_counters] == false
inc_options['voteable.votes_count'] = 1
if value == :up
inc_options['voteable.up_votes_count'] = 1
@@ -195,7 +197,6 @@ def self.vote(options)
)
end
end
-
true
end
@@ -228,26 +229,6 @@ def vote_value(voter)
return :down if down_voter_ids.include?(voter_id)
end
- # Get the number of up votes
- def up_votes_count
- voteable.try(:[], 'up_votes_count') || 0
- end
-
- # Get the number of down votes
- def down_votes_count
- voteable.try(:[], 'down_votes_count') || 0
- end
-
- # Get the number of votes
- def votes_count
- voteable.try(:[], 'votes_count') || 0
- end
-
- # Get the votes point
- def votes_point
- voteable.try(:[], 'votes_point') || 0
- end
-
# Array of up voter ids
def up_voter_ids
voteable.try(:[], 'up_voter_ids') || []
@@ -258,9 +239,9 @@ def down_voter_ids
voteable.try(:[], 'down_voter_ids') || []
end
- private
- def voteable
- read_attribute('voteable')
- end
+ def voteable
+ read_attribute('voteable')
+ end
+
end
end
View
104 lib/voteable_mongoid/voteable/stats.rb
@@ -0,0 +1,104 @@
+module Mongoid
+ module Voteable
+ module Stats
+ extend ActiveSupport::Concern
+
+ included do
+ index 'voteable.up_votes_count'
+ index 'voteable.down_votes_count'
+ index 'voteable.votes_count'
+ index 'voteable.votes_point'
+
+ scope :most_up_voted, order_by(['voteable.up_votes_count', :desc])
+ scope :most_down_voted, order_by(['voteable.down_votes_count', :desc])
+ scope :most_voted, order_by(['voteable.votes_count', :desc])
+ scope :best_voted, order_by(['voteable.votes_point', :desc])
+ end
+
+ def self.remake_stats
+ Mongoid::Voteable::VOTE_POINT.each do |class_name, value_point|
+ klass = class_name.constantize
+ klass_value_point = value_point[class_name]
+ klass.voteable_related.each{ |doc|
+ doc.remake_stats(klass_value_point)
+ }
+ end
+
+ VOTE_POINT.each do |class_name, value_point|
+ klass = class_name.constantize
+ value_point.each do |parent_class_name, parent_value_point|
+ relation_metadata = klass.relations[parent_class_name.underscore]
+ if relation_metadata
+ parent_class = parent_class_name.constantize
+ foreign_key = relation_metadata.foreign_key
+ klass.voteable_related.each{ |doc|
+ doc.update_parent_stats(parent_class, foreign_key, parent_value_point)
+ }
+ end
+ end
+ end
+ end
+
+ def remake_stats(value_point)
+ up_count = up_voter_ids.length
+ down_count = down_voter_ids.length
+ # puts "#{self.class}(#{id}): #{up_count}, #{down_count}" # DEBUG
+ update_attributes(
+ 'voteable.up_votes_count' => up_count,
+ 'voteable.down_votes_count' => down_count,
+ 'voteable.votes_count' => up_count + down_count,
+ 'voteable.votes_point' => value_point[:up]*up_count + value_point[:down]*down_count
+ )
+ end
+
+ def update_parent_stats(parent_class, foreign_key, value_point)
+ parent_id = read_attribute(foreign_key.to_sym)
+ if parent_id
+ up_count = up_voter_ids.length
+ down_count = down_voter_ids.length
+
+ return if up_count == 0 && down_count == 0
+
+ inc_options = {
+ 'voteable.votes_point' => value_point[:up]*up_count + value_point[:down]*down_count
+ }
+
+ unless value_point[:update_counters] == false
+ inc_options.merge!(
+ 'voteable.votes_count' => up_count + down_count,
+ 'voteable.up_votes_count' => up_count,
+ 'voteable.down_votes_count' => down_count
+ )
+ end
+
+ # puts inc_options.inspect # DEBUG
+ parent_class.collection.update(
+ { :_id => parent_id },
+ { '$inc' => inc_options }
+ )
+ end
+ end
+
+ # Get the number of up votes
+ def up_votes_count
+ voteable.try(:[], 'up_votes_count') || 0
+ end
+
+ # Get the number of down votes
+ def down_votes_count
+ voteable.try(:[], 'down_votes_count') || 0
+ end
+
+ # Get the number of votes
+ def votes_count
+ voteable.try(:[], 'votes_count') || 0
+ end
+
+ # Get the votes point
+ def votes_point
+ voteable.try(:[], 'votes_point') || 0
+ end
+
+ end
+ end
+end
View
0  lib/mongoid/voter.rb → lib/voteable_mongoid/voter.rb
File renamed without changes
View
2  spec/models/comment.rb
@@ -7,5 +7,5 @@ class Comment
referenced_in :post
vote_point self, :up => +1, :down => -3
- vote_point Post, :up => +2, :down => -1
+ vote_point Post, :up => +2, :down => -1 #, :not_update_counters => true
end
View
35 spec/voteable_spec.rb → spec/voteable_mongoid/voteable_spec.rb
@@ -8,7 +8,6 @@
@post2 = Post.create!
@comment = @post2.comments.create!
-
@user1 = User.create!
@user2 = User.create!
end
@@ -61,6 +60,7 @@
context 'user1 vote up post1 the first time' do
before :all do
Post.vote(:votee_id => @post1.id, :voter_id => @user1.id, :value => :up)
+ Mongoid::Voteable::Stats.remake_stats
@post1.reload
end
@@ -93,6 +93,7 @@
context 'user2 vote down post1 the first time' do
before :all do
Post.vote(:votee_id => @post1.id, :voter_id => @user2.id, :value => :down)
+ Mongoid::Voteable::Stats.remake_stats
@post1.reload
end
@@ -113,6 +114,7 @@
context 'user1 change vote on post1 from up to down' do
before :all do
Post.vote(:revote => true, :votee_id => @post1.id, :voter_id => @user1.id, :value => :down)
+ Mongoid::Voteable::Stats.remake_stats
@post1.reload
end
@@ -133,6 +135,7 @@
context 'user1 vote down post2 the first time' do
before :all do
Post.vote(:votee_id => @post2.id, :voter_id => @user1.id, :value => :down)
+ Mongoid::Voteable::Stats.remake_stats
@post2.reload
end
@@ -152,6 +155,7 @@
context 'user1 change vote on post2 from down to up' do
before :all do
Post.vote(:revote => true, :votee_id => @post2.id.to_s, :voter_id => @user1.id.to_s, :value => :up)
+ Mongoid::Voteable::Stats.remake_stats
@post2.reload
end
@@ -172,6 +176,7 @@
context 'user1 vote up post2 comment the first time' do
before :all do
@comment.vote(:voter_id => @user1.id, :value => :up)
+ Mongoid::Voteable::Stats.remake_stats
@comment.reload
@post2.reload
end
@@ -193,6 +198,7 @@
context 'user1 revote post2 comment from up to down' do
before :all do
@user1.vote(:votee => @comment, :value => :down)
+ Mongoid::Voteable::Stats.remake_stats
@comment.reload
@post2.reload
end
@@ -227,6 +233,7 @@
context "user1 unvote on post1" do
before(:all) do
@post1.vote(:voter_id => @user1.id, :votee_id => @post1.id, :unvote => true)
+ Mongoid::Voteable::Stats.remake_stats
@post1.reload
end
@@ -269,11 +276,12 @@
context "user1 unvote on comment" do
before(:all) do
@user1.unvote(@comment)
+ Mongoid::Voteable::Stats.remake_stats
@comment.reload
@post2.reload
end
- it "" do
+ it "" do
@post2.up_votes_count.should == 1
@post2.down_votes_count.should == 0
@post2.votes_count.should == 1
@@ -285,4 +293,25 @@
@comment.votes_point.should == 0
end
end
-end
+
+ context 'final' do
+ it "test remake stats" do
+ Mongoid::Voteable::Stats.remake_stats
+
+ @post1.up_votes_count.should == 0
+ @post1.down_votes_count.should == 1
+ @post1.votes_count.should == 1
+ @post1.votes_point.should == -1
+
+ @post2.up_votes_count.should == 1
+ @post2.down_votes_count.should == 0
+ @post2.votes_count.should == 1
+ @post2.votes_point.should == 1
+
+ @comment.up_votes_count.should == 0
+ @comment.down_votes_count.should == 0
+ @comment.votes_count.should == 0
+ @comment.votes_point.should == 0
+ end
+ end
+end
View
0  spec/voter_spec.rb → spec/voteable_mongoid/voter_spec.rb
File renamed without changes
Please sign in to comment.
Something went wrong with that request. Please try again.