数据库恶作剧:如何让我的网站“记住”用户投票?

时间:2012-04-19 02:05:06

标签: ruby-on-rails ruby ruby-on-rails-3 ruby-on-rails-3.1

我的代码的基本概要是:

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

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

  3. 为其指定一个值(upvote vs. downvote)

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

  5. 虽然这是问题所在......即使数据库中存在(显然)存在,程序也永远无法查找投票对象!

    我的代码如下所示:

        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 =&gt;: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
    

1 个答案:

答案 0 :(得分:0)

检查Dynamic attribute-based finders。您应该可以执行以下操作:(未经测试的代码)

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

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