如果使用first_or_create"首先"或"创建"某些内容,我如何区分

Tal*_*boy 1 ruby ruby-on-rails ruby-on-rails-3 ruby-on-rails-3.1

我正在尝试使用此声明:

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

这是一个upvote或downvote.如果该行不存在于DB中,则应该创建它(如果它们从未在该帖子上投票),则应该使用-1,0,1来修改该值.

如果他们第二次点击upvote,它需要"撤销"投票并将行"值"设置为0而不是1.同样的事情发生在downvote但是现在只是upvote函数.

我在调试这个语句时遇到了麻烦.我需要基本上区分它是保存的记录还是创建的记录.如果我把:

@vote = Vote.where(:resource_id => 25, :user_id => 1)
@vote.exists?
Run Code Online (Sandbox Code Playgroud)

我明白了 true

但如果我把它...(和记录存在,它只是在上面工作)..

@vote = Vote.where(:resource_id => 25, :user_id => 1).first_or_create(:value => 1)
@vote.exists?
Run Code Online (Sandbox Code Playgroud)

我得到... 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
Run Code Online (Sandbox Code Playgroud)

Ste*_*ose 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)
Run Code Online (Sandbox Code Playgroud)

如果您不希望它立即创建,您可以使用find_or_initialize_by哪个基本上创建一个Vote.new不保存.

  • Model.where(:something =>"value").first_or_create(:somedefault => 123).[指南](http://guides.rubyonrails.org/active_record_querying.html#first_or_create)或[APIDock](http://apidock.com/rails/ActiveRecord/Relation/first_or_create) (3认同)