I'm currently using the thumbs_up gem to allow my users to vote on posts and am having an issue with the vote_exclusively_for/against methods. Here is the gem's github link: https://github.com/brady8/thumbs_up. The gem works fine with the vote_up and vote_down methods, but when I change it to vote_exclusively_for (which is supposed to replace a previous down vote w/ an up vote), I get the following error in my development log:
ActiveRecord::RecordInvalid (Validation failed: Voteable has already been taken):
app/controllers/posts_c开发者_如何学Goontroller.rb:97:in `vote_up'
It appears that a method inside the gem is not clearing out the previous vote before initiating the new vote. Here is my code in the posts_controller:
def vote_up
@user = current_user
@post = Post.find(params[:id])
@user.vote_exclusively_for(@post)
redirect_to (..)
end
Here is the code from the gem:
def vote_exclusively_for(voteable)
self.vote(voteable, { :direction => :up, :exclusive => true })
end
def vote(voteable, options = {})
raise ArgumentError, "you must specify :up or :down in order to vote" unless options[:direction] && [:up, :down].include?(options[:direction].to_sym)
if options[:exclusive]
self.clear_votes(voteable)
end
direction = (options[:direction].to_sym == :up)
Vote.create!(:vote => direction, :voteable => voteable, :voter => self)
end
def clear_votes(voteable)
Vote.where(
:voter_id => self.id,
:voter_type => self.class.name,
:voteable_id => voteable.id,
:voteable_type => voteable.class.name
).map(&:destroy)
end
I'm not sure why the clear_votes method isn't deleting the previous vote. Any help would be greatly appreciated.
Try running this in the console and see if it works or not:
user = ... # fetch the right user
post = ... # fetch the right post
Vote.where(
:voter_id => user.id,
:voter_type => User,
:voteable_id => post.id,
:voteable_type => Post
).map(&:destroy)
You can also temporarily edit clear_votes
and do some logging there to make sure that the self.class.name
and voteable.class.name
are referring to the right classes. Also log the where
method call with a count
before the map to the destroy command to ensure that it's not returning an empty array.
精彩评论