So I've implemented a voting system, and in my view where I print video.vote_sum
, the value for one of the video's vote_sum displays 1. However when I run Video.find(450)
in my console, I see that the element actually has a vote_sum of two. I'm not sure why this is happening, and although the voting works as it should, when I reload the page, the pluralize
method in my view displays "1 votes". But this is only upon a page reload. When I'm voting, it displays "1 vote". Weird.
Here's the create method in the video_votes controller:
def create
@video = Video.find(params[:video_id])
@vote = current_user.video_votes.find_or_create_by_video_id(@video.id)
if @vote.value.nil?
if params[:type] == "up"
@vote.value = 1
else
@vote.value = -1
end
elsif (params[:type] == "up" && @vote.value == 1) || (params[:type] == "down" && @vote.value == -1)
@vote.value = 0
elsif ((params[:type] == "up" && @vote.value == -1) || (params[:type] == "down" && @vote.valu开发者_如何学Pythone == 1)) || (@vote.value == 0)
if params[:type] == "up"
@vote.value = 1
else
@vote.value = -1
end
end
if @vote.save
respond_to do |format|
format.html { redirect_to @video }
format.js
end
else
respond_to do |format|
format.html { redirect_to @video }
format.js {render 'fail_create.js.erb'}
end
end
end
Here's the relevant code in my Video model:
def vote_sum
video_votes.sum(:value)
end
And here's the relevant code in my video_vote model:
after_update :update_vote_sum
private
def update_vote_sum
video.update_attributes!(:vote_sum => video.vote_sum + value)
end
Why is this happening, and how could I fix it?
I believe this is a problem with your view and the way you're using pluralize
--you're supposed to pass it the singular version of your noun, and optionally a plural version (in case it can't guess it correctly).
Please see my change on GitHub.
Here's a screenshot:
[Update]
After messing with your app, somehow it's possible to get video.vote_sum
(the actual database value) to be different than video.video_votes.sum(:value)
; I'm not yet sure why. However, you do have another issue with your codebase, demonstrated below:
ruby-1.9.2-p136 :001 > v = Video.find 2
=> #<Video id: 2, ... video_votes_count: 0, vote_sum: 3>
ruby-1.9.2-p136 :002 > v.video_votes.sum(:value)
=> 2
ruby-1.9.2-p136 :003 > v.vote_sum
=> 2 # doesn't match vote_sum in the database!
You have a method called vote_sum
on your Video
model. This means when you access @video.vote_sum
, you are NOT accessing the vote_sum
property from the model from the database, because you overwrite that functionality. This makes it pointless to update vote_sum
in VideoVote
's after_create
because you can never access it (as demonstrated in my IRB session, above).
You should to reload the video:
if @vote.save
@video.reload
respond_to do |format|
format.html { redirect_to @video }
There might be other way to reload vote_sum
only without reloading @video
but this should be quite enough for the start.
Also please note you could have a better use of model :counter_cache
when you would separate up
and down
votes to separate relation/models ... it's sad but sometimes to get full power of rails you need to make freaky things with your models.
精彩评论