开发者

Weird discrepancy between database value and value display in view

开发者 https://www.devze.com 2023-02-18 23:38 出处:网络
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 t

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:

Weird discrepancy between database value and value display in view

[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.

0

精彩评论

暂无评论...
验证码 换一张
取 消