0

問題が発生しましたが、現時点で私のソリューションは非常に見苦しいと思います。レール/モンゴイドで次のことを行うより良い方法は何ですか? 基本的に、ユーザーは「nil」の answer_id を入力して提供できますが、ユーザーが質問に答えるとすぐに、最初の非 nil の回答をロックしたいと考えています。

controller.rb

r = Response.new(user: current_user, question_id: qid, answer_id: aid)
r.save_now!

そして、次の response.rb モデル:

def save_now!
    user = self.user
    qid = self.question_id
    aid = self.answer_id
    resp = Response.where({user_id: user._id, question_id: qid}).first

    # We accept the first answer that is non-nil, 
    # so a user can skip the question (answer_id=nil)
    # And then return and update the answer_id from nil to 'xyz'
    if resp.nil?
      resp = Response.new(user: user, question_id: qid, answer_id: aid)
    else
      if resp.answer_id.nil? && aid.present?
         resp.answer_id = aid
      end    
    end    
    resp.save!
end

したがって、最初に answer_id を nil にして (ユーザーが質問をスキップした場合)、nil 以外の最初の回答を取得したいと思います。

コントローラで 1 回、モデルで 1 回、Response オブジェクトを 2 回インスタンス化するのは直感的でクリーンだとは思いませんが、これを行う最善の方法はわかりません。ありがとう。

4

2 に答える 2

1

に一意のインデックスを作成します(user, question_id, answer_id)。このように、最初の挿入のみが成功します。以降の挿入はエラーで失敗します。これにより、メソッドでfindクエリを実行する必要がなくなりますsave_now!

この挿入をセーフモードで実行することを忘れないでください。そうしないと、例外が発生せず、サイレントに失敗します。

アップデート

メソッドの名前を変更することで問題が解決する可能性があるようです。:)見てください:

class Response
  def self.save_answer(user, qid, aid)
      resp = Response.where({user_id: user._id, question_id: qid}).first

      if resp.nil?
        resp = Response.new(user: user, question_id: qid, answer_id: aid)
      else
        if resp.answer_id.nil? && aid.present?
           resp.answer_id = aid
        end    
      end    
      resp.save!
  end
end

# controller.rb
r = Response.save_answer(current_user, qid, aid)
于 2012-07-11T16:18:11.733 に答える
-1

Mongoid には、使用できる一意性に関する検証があります。あなたの場合、user、question_id、および answer_id に複合インデックスを作成でき、save_answer メソッドを記述する必要はありません。

たとえば、これを Response モデルに入れることができます。

validates_uniqueness_of :user_id, :question_id

ユーザーごとに 1 つの質問に対して 1 つの回答しかできないようにするため。

于 2012-07-11T18:13:37.010 に答える