Voteable Mongoid
Voteable Mongoid allows you to make your Mongoid::Document objects voteable (up or down). For instance, in a forum, a user can vote up (or down) on a post or a comment.
Initial idea is based on cookbook.mongodb.org/patterns/votes
Voteable Mongoid is built for speed. It uses only one database request per collection to validate data, update data, and get updated data.
Sample app at github.com/vinova/simple_qa
Installation
Rails 3.0.x
To install the gem, add this to your Gemfile
gem 'voteable_mongoid'
After that, remember to run “bundle install”
Usage
Making Post and Comment voteable, User being the voter
post.rb
class Post
include Mongoid::Document
include Mongoid::Voteable
# set points for each vote
voteable self, :up => +1, :down => -1
references_many :comments
end
comment.rb
require 'post'
class Comment
include Mongoid::Document
include Mongoid::Voteable
referenced_in :post
voteable self, :up => +1, :down => -3
# each vote on a comment can affect votes count and point of the related post as well
voteable Post, :up => +2, :down => -1
end
user.rb
class User
include Mongoid::Document
include Mongoid::Voter
end
Making a vote
@user.vote(@post, :up)
Is equivalent to
@user.vote(:votee => @post, :value => :up)
@post.vote(:voter => @user, :value => :up)
In case you don't need to init voter and / or votee objects you can
@user.vote(:votee_type => 'Post', :votee_id => post_id, :value => :down)
@post.vote(:voter_id => user_id, :value => :up)
Post.vote(:voter_id => user_id, :votee_id => post_id, :value => :up)
Undo a vote
@user.unvote(@comment)
If have voter_id, votee_id and vote value you don't need to init voter and votee objects (suitable for API calls)
New vote
Post.vote(:voter_id => user_id, :votee_id => post_id, :value => :up)
Re-vote
Post.vote(:voter_id => user_id, :votee_id => post_id, :value => :up, :revote => true)
Un-vote
Post.vote(:voter_id => user_id, :votee_id => post_id, :value => :up, :unvote => true)
In-case you need updated votes data, add :return_votes => true
votes = Post.vote(:voter_id => user_id, :votee_id => post_id, :value => :up, :return_votes => true)
votes['up'] # => up_voter_ids who voted up
votes['down'] # => down_voter_ids who voted down
votes['up_count'] # => number of up votes (votes_voter_ids.length)
votes['down_count'] # => number of down votes (down_voter_ids.length)
votes['count'] # => number of votes (up_count + down_count)
votes['point'] # => total vote points
Getting vote_value
@user.vote_value(@post)
@user.vote_value(:class_type => 'Post', :votee_id => post_id)
@post.vote_value(@user)
@post.vote_value(user_id)
Check if voted?
@user.voted?(@post)
@user.voted?(:class_type => 'Post', :votee_id => post_id)
@post.voted_by?(@user)
@post.voted_by?(user_id)
Getting votes counts and points
puts @post.votes_point
puts @post.votes_count
puts @post.up_votes_count
puts @post.down_votes_count
Getting the list of voted objects of a class
Post.voted_by(@user)
Post.up_voted_by(@user)
Post.down_voted_by(@user)
Utilities
Re-generate counters and vote points in case you change :up / :down vote points
Rails
rake db:mongoid:voteable:remake_stats
Ruby
Mongoid::Voteable::Tasks.remake_stats
Set counters and point to 0 for uninitialized voteable objects in order sort and query
Rails
rake db:mongoid:voteable:init_stats
Ruby
Mongoid::Voteable::Tasks::init_stats
Migrate from version < 0.7.0
Rails
rake db:mongoid:voteable:migrate_old_votes
Ruby
Mongoid::Voteable::Tasks.migrate_old_votes
Credits
-
Alex Nguyen (alex@vinova.sg) - Author
-
Stefan Nguyen (stefan@vinova.sg) - Unvoting
Copyright © 2010-2011 Vinova Pte Ltd (vinova.sg)
Licensed under the MIT license.