1

我正在尝试使用此语句:

@vote = Vote.where(:resource_id => params[:id], :user_id => current_user.id).first_or_create(:value => 1)

这是为了赞成或反对。如果数据库中不存在该行,它应该创建它(他们从未对该帖子投票),否则它应该用-1,0,1修改该值。

如果他们第二次单击 upvote,则需要“撤消”投票并将行“值”设置为 0 而不是 1。downvote 也会发生同样的情况,但这只是目前的 upvote 功能。

尽管在 Rails 中调试此语句时遇到问题。我需要基本上区分它是保存的记录还是创建的记录。如果我说:

@vote = Vote.where(:resource_id => 25, :user_id => 1)
@vote.exists?

我明白了true

但是如果我把这个..(并且记录确实存在,它只是在上面工作)..

@vote = Vote.where(:resource_id => 25, :user_id => 1).first_or_create(:value => 1)
@vote.exists?

我得到... NoMethodError:未定义的方法“存在吗?” 为了 #

在查看了两个对象的类后,我看到一个是“投票”,一个是“ActiveRecord::Relation”。

我的最终目标是以某种方式重构它(主要是检查投票值是否已经为 1 的部分,如果是,则将其设置为零(撤消投票),否则将其设置为 1

这是我开始尝试使用 first_or_create 重构之前的代码。它又长又丑。

 if @vote.exists?
      # Check if they have already voted
      if @vote.first.value == 1
        @vote.first.value = 0
      else
        @vote.first.value = 1
      end
      flash[:notice] = "previous vote modified"
      @vote.first.save
    else
      # Create a new Vote instance, save it
      @vote = Vote.new(:resource_id => params[:id], :user_id => current_user.id, :value => 1)
      if @vote.valid?
        @vote.save
        flash[:notice] = "New vote added"
      else
        @vote.save
        flash[:notice] = (@vote.errors.full_messages).to_s
      end
    end
4

1 回答 1

5

我会改为使用 Rails 魔术方法find_or_create_by方法。

在此处查看“基于动态属性的查找器”:

http://api.rubyonrails.org/classes/ActiveRecord/Base.html

您可以像使用动态查找方法一样使用它,但如果不存在,则传入要添加的额外变量以创建投票。

在你的情况下,它会是这样的:

@vote = Vote.find_or_create_by_resource_id_and_user_id(25, 1, :value => 1)

如果您不希望它立即创建,您可以使用find_or_initialize_bywhich 实际上创建一个Vote.new而不保存。

于 2012-05-10T16:14:38.547 回答