我正在尝试使用此声明:
@vote = Vote.where(:resource_id => params[:id], :user_id => current_user.id).first_or_create(:value => 1)
这是一个upvote或downvote。如果该行不存在于DB中,则应该创建它(如果他们从未在该帖子上投票),则应该使用-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
答案 0 :(得分: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_by
而不保存的Vote.new
。