1

所以我真的认为这将有助于创建我们在 SO 上的投票系统:

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.value == 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

我尝试按照这个问题中第一个答案的示例进行操作:为什么这个 Ruby on Rails 代码没有按我的预期工作?但是,由于此错误,我的代码不允许我第一次对视频进行投票:

TypeError (nil can't be coerced into Fixnum):
app/models/video_vote.rb:11:in `update_vote_sum'
app/controllers/video_votes_controller.rb:4:in `create

这是我的视频投票模型:

class VideoVote < ActiveRecord::Base
  belongs_to :user
  belongs_to :video
  validates_uniqueness_of :user_id, :scope => :video_id

  after_create :update_vote_sum

  private

    def update_vote_sum
      video.update_attributes!(:vote_sum => video.vote_sum + value)
    end
end

如果需要,这是vote_sum我的视频模型中的方法:

def vote_sum
  video_votes.sum(:value)
end
4

2 回答 2

3

在您的after_create方法中VideoVote.rb,您正在对所有投票求和,包括您刚刚创建的带有 nil 值的投票。切换after_createafter_update或将默认值设置为valueon VideoVote

看这个,如果无论如何每次vote_sum都调用你所有的投票,如果投票设置了默认值sum,你可能甚至不需要after_createor方法。after_update

--

您也可以用thumbs_up gem替换整个系统,这样可以省去一些麻烦。

于 2011-03-19T17:42:47.767 回答
0

不确定您要在这里做什么。vote_sum是一种总结视频投票数的方法,据我所知,您为什么要尝试将其更新为属性?它将始终返回视频的正确分数,您不需要手动更新它,因为它不是属性,而是方法的计算结果。

于 2011-03-19T17:53:30.360 回答