1

私はこのステートメントを使おうとしています:

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

これは賛成票または反対票用です。行がDBに存在しない場合は、それを作成する必要があります(その投稿に投票したことがない場合)。それ以外の場合は、値を-1,0,1に変更する必要があります。

もう一度賛成票をクリックした場合は、投票を「元に戻す」必要があり、行「value」を1ではなく0に設定する必要があります。反対票でも同じことが起こりますが、これは現在の賛成票機能のみです。

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:未定義のメソッドが「存在しますか?」にとって #

2つのオブジェクトのクラスを見ると、1つは「投票」で、もう1つは「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_byに基本的に作成するものを使用できます。Vote.new

于 2012-05-10T16:14:38.547 に答える