Acts As Voteable Rails Plugin
Jun13
Right on the heels of my release of acts_as_commentable, I am now making available a acts_as_voteable Ruby on Rails plugin. The Acts As Voteable plugin allows for model to be voted on by users.
To install this plugin run the following command:
script/plugin install http://juixe.com/svn/acts_as_voteable
The installation process will add several ruby files in the vendor/plugins directory. Create a new rails migration and cut and past the following self.up and self.down methods:
def self.up
create_table :votes, :force => true do |t|
t.column :vote, :boolean, :default => false
t.column :created_at, :datetime, :null => false
t.column :voteable_type, :string, :limit => 15,
:default => "", :null => false
t.column :voteable_id, :integer, :default => 0, :null => false
t.column :user_id, :integer, :default => 0, :null => false
end
add_index :votes, ["user_id"], :name => "fk_votes_user"
end
def self.down
drop_table :votes
end
Once you have installed the plugin you can start using it in your ActiveRecord models simply by calling the acts_as_voteable method.
class Post < ActiveRecord::Base acts_as_voteable end
To cast a vote for a post you can do the following:
vote = Vote.new(:vote => true) post = Post.find(params[:id]) post.votes << vote
ActiveRecord models that act as voteable can be queried for the positive votes, negative votes, and a total vote count by using the votes_for, votes_against, and votes_count methods respectively. Here is an example:
positiveVoteCount = post.votes_for negativeVoteCount = post.votes_against totalVoteCount = post.votes_count
And because the Acts As Voteable plugin will add the has_many votes relationship to your model you can always get all the votes by using the votes property:
allVotes = post.votes
Technorati Tags: ruby, rails, ruby on rails, plugin, rails plugin, acts_as_commentable, acts_as_voteable











1:32 pm on March 30th, 2007
hey, lots of good stuff up here. sadly, I think the acts_as_voteable is broken. firstly the :submitted above should probably be :created_at as there is no submitted attribute in votes.
also the voted_for and voted_against methods use TRUE and FALSE which errors in mySQL since mySQL uses int(1) for boolean types. is there a reason for this? i hate to see good plugins fall out of service.
10:23 am on April 4th, 2007
@Lawrence - Thanks for bringing this to my attention. On MySQL 4.1.15, the vote column is a tinyint(1) and I get no error casting votes. I guess I could just use 1/0 instead of TRUE/FALSE to cast a vote. Let me read up on booleans on MySQL…
7:50 pm on April 11th, 2007
Hey,
Thanks for this plugin. There is one thing though, I would like to go for the route of allowing a user to vote from 1 through 5, instead of a basic vote for 1 point for e.g (that’s what your plugin currently acts as).
How would I implement such a functionality? Could it be done with some slight modification to your plugin?
11:47 am on April 18th, 2007
Hi, Thanks for the plugin, but for some reason it does not work for me. I have done what you have mentioned but it does not work and does not recognize the acts_as_voteable class or method.
Please tell me how i can fix this.
I’m using instantrails version 1.7
9:07 pm on May 16th, 2007
I had a 1 N database problem with using acts_as_voteable when applied to a list of comments. I solved this with some updated code. If you are including in the votes table correctly, this will yield 0 extra database hits and hopefully squeeze out some extra performance.
def votes_for votes_with_vote_of true end def votes_against votes_with_vote_of false end def votes_with_vote_of(vote) count = 0 self.votes.each { |v| count = 1 if v.vote == vote } count end5:06 pm on June 5th, 2007
I have no been able to get a validation working with act_as_voteable
How would I handle checking that the user_id, voteable_id, and vote are unique so the same person cant vote twice on the same post?
I’ve tried putting “validates_uniquness_of” everywhere but its not working. Under the Post.rb its not validating but the vote is still being entered in the db.
thanks
Dan
lifedmedia [at] gmail [dot] com
2:54 pm on July 13th, 2007
I had the same issue as Dan, but I solved it by creating a new instance method.
Just stick this under module InstanceMethods
def vote (value, user) if user self.votes.each { |v| if user.id == v.user_id if v.vote == value return false else v.update_attribute(:vote, value) return true end end } self.votes value, :user_id => user.id) return true end endTo use it just call rated_item.vote value, user for instance: ad.vote true, user
One quick caveat, you need to pass it actual boolean values or the comparison doesn’t work (at least with MySQL). So I have
in my controller. Hope this helps someone…
12:45 pm on August 1st, 2007
Is a reputation system planned (i.e. each vote can have a weight based on the user that expressed it)?
If not, any idea on how it should be implemented?
Keeping the reputation count in User can be expensive when retrieving the vote count for a voteable (each vote would have to be multiplied by the reputation every time), but storing the reputation in the vote it’s not right because it varies with time.
What do you think?
4:04 am on February 26th, 2008
It’s been a while since you’ve made changes.. but I was wondering, is there a “neutral” vote?
4:42 pm on July 13th, 2008
I’ve added some functionality to this plugin, updated it to use named_scopes, the polymorphic keyword, and a couple other goodies.
I’m planning to add ranged voting (configurable as 1..10, etc) and karma-weighted voting as well.
Not sure if acts_as_voteable is still being maintained. If it is, I’m happy to fold my changes into the main project.
Otherwise, you can see my enhancements on GitHub, Vote Fu.
8:36 am on October 4th, 2008
Hello, you have an error in the module acts_as_voteable.rb:
on line 12:
:dependent => :true
On rails 2.1.1 :dependent => :true raises a fatal error. You can change for :nullify with the same effects to correct this error.
Regards.
2:31 am on November 14th, 2008
@Lukas: you just need to edit lib/acts_as_votable.rb under plugin directory. And change :dependent=>true to :dependent=>:destroy. it will work fine.