0

我的代码的基本大纲是这样的:

  1. 检查用户是否有与特定“报告”关联的“投票”对象

  2. 如果没有这样的投票对象,则创建一个。

  3. 给它一个值(upvote vs. downvote)

  4. 如果存在这样的投票对象,则更改现有投票的值。

但问题是……即使它(显然)存在于数据库中,程序也永远不会找到投票对象!

我的代码如下所示:

    def vote_up # voting code
      @was_new = false

      current_report = Report.find(params[:id])
      @report = current_report

      begin
        @vote = current_report.votes.find_by_user_id(current_user.id) #<<---HERE IS THE BUG!!
      rescue
        @was_new = true
        @vote = Vote.create(:user_id => current_user.id, :votable_type => 'Report', :value => 0)   # default vote score of zero
      end

      current_report.votes << @vote
      current_report.save

      if @was_new #if the vote was new...
        @report.upvotes += 1
        @vote.value = 1

      elsif !@was_new and @vote.value == -1 #else, if you are changing your vote...

        @report.upvotes += 1
        @report.downvotes -= 1
        @vote.value = 1

      end

        @vote.save
        @report.save

        redirect_to(report_path(@report))
    end

我收到的错误是这样的:

 SQLite3::SQLException: no such column: votes.votable_id: SELECT  "votes".* FROM "votes"  WHERE "votes"."votable_id" = 3 AND "votes"."votable_type" = 'Report' AND "votes"."user_id" = 1 LIMIT 1

我觉得解决方案很简单,比如写 @vote = current_report.votes.find(params[:user_id], :as => :user_id) 或类似的东西。

编辑:

我让它工作了。这是工作代码:

 def vote_up # voting code

 @exists = false

 get_vote(1)

 if !@exists #if the vote was new...
  @report.upvotes += 1

elsif @exists and @vote.value == -1 #else, if you are changing your vote...

  @report.upvotes += 1
  @report.downvotes -= 1
  @vote.value = 1

    end

    @vote.save
    @report.save

 redirect_to(report_path(@report))

end

def vote_down

 @exists = false

    get_vote(-1)

    if !@exists # this should handle vote changing
  @report.downvotes += 1

  elsif @exists and @vote.value == 1

  @report.downvotes += 1
  @report.upvotes -= 1
  @vote.value = -1

    end

    @vote.save
    @report.save

redirect_to(report_path(@report))

end

 def get_vote(val) # voting code
 current_report = Report.find(params[:id])

 @report = current_report
 @vote = current_report.votes.find_by_user_id(current_user.id) 

 unless @vote # create a vote only if it's nil
   @vote = Vote.create(:user_id => current_user.id, :votable_id => 3, :votable_type => 'Report',  :value => val) # default vote score of zero
   current_report.votes << @vote
  current_report.save
 else #if it's not nil
  @exists = true
end

end
4

1 回答 1

0

检查基于动态属性的查找器。您应该能够执行以下操作:(未经测试的代码)

def vote_up # voting code
  current_report = Report.find(params[:id])
  @report = current_report

  # gets the vote or initialize a new one for that user_id
  @vote = current_report.votes.find_or_initialize_by_user_id(current_user.id) 

  if !@vote.saved?
    @vote.votable_type = 'Report' 
    @vote.value = 0
    #  current_report.votes << @vote #not sure if it's necessary
    #  current_report.save #not sure if it's necessary

    @report.upvotes += 1
    @vote.value = 1
  elsif @vote.value == -1 
    @report.upvotes += 1
    @report.downvotes -= 1
    @vote.value = 1
  end

  @vote.save
  @report.save  

  redirect_to(report_path(@report))
end

重要提示:还有一件事。您应该将此方法的大部分移植到您的 Report 模型中,这显然是一个商业问题,所以它应该去哪里!

于 2012-04-19T04:23:21.877 回答