1

我有一个答案模型,它属于具有“正确”布尔列的问题。理想情况下,一个问题只能有 1 个正确答案(很像 stackoverflow 系统)。

我有以下控制器+模型代码,它使用一种toggle_correct方法来切换视图中的“正确”布尔值(所有这些都很好)。

当我尝试创建新答案时,one_correct_answer即使正确的列设置为默认值,也会引发验证错误:迁移中的 false 并且应用程序 POST 跟踪中的值设置为 0 (false)

如何修改我的代码,以便此验证仅允许每个问题有 1 个正确答案,并且不会中断新答案对象的创建?

答案.rb

validate :one_correct_answer

  def one_correct_answer
    answers = self.question.answers.map(&:correct)
    errors.add(:user_id, "You can't have more than 1 correct answer #{answers}") if answers & [true]
    logger.debug("Answers array #{answers}")
  end

def toggle_correct(attribute)
    toggle(attribute).update_attributes({attribute => self[attribute]})
  end 

answers_controller.rb

def correct 
    @answer = Answer.find(params[:id])
    if @answer.toggle_correct(:correct)
    respond_to do |format|
      format.html { redirect_to :back, notice: "Answer submitted" }
      format.js
      end
    end
  end

_answer.html.erb

<div id="correct_answer_<%= answer.id %>" class="<%= answer.correct == true ? 'green-tick' : 'default-tick' %>">
    <% if answer.question.user == current_user %>
        <%= link_to "✓", correct_answer_path(answer), id: "tick", class: "correct_#{answer.id}", remote: true, method: :put %>
    <% else %>
        <% if answer.correct == true %>
           <div id="tick", class='correct_<% answer.id %>'> ✓&lt;/div>
        <% end %>
    <% end %>
</div>
4

2 回答 2

1

你的问题可能在这里:

errors.add(:user_id, "You can't have more than 1 correct answer #{answers}") if answers & [true]

answers & [true]将始终返回一个数组(因为answers是一个数组),而空白数组是 Ruby 中的真值。

即使它们是错误值,您的条件也不会起作用,因为必须有一个正确答案,并且您的条件会检查是否没有正确答案。

我会使用这个条件:

self.question.answers.count(&:correct) <= 1
于 2013-06-03T06:43:50.383 回答
1

它失败的原因是,如果与问题相关的任何答案都是正确的,则您正在添加一个错误。即使您尝试保存的答案是否正确,您也会对此进行测试。因此,您应该做的第一件事是仅在您尝试保存的答案确实正确时检查是否有任何正确答案,如下所示:

validate :one_correct_answer, if: :correct?

这样,只有当当前答案正确时,才会验证 one_correct_answer 方法。

但是,您还有一个额外的问题。如果您尝试保存的答案是正确的,则将调用该方法,如果有任何正确的答案,它将添加一个错误......这可能是因为当前答案也应该列在该关联中. 因此,您要做的是检查是否有正确的附加答案。

所以最后,我可能最终会像这样验证它:

validates_uniqueness_of :correct, scope: :question_id, if: :correct?

这样做的目的是验证 question_id 列和正确列的唯一组合,但前提是正确为真。这使得每个问题可以有多个错误但只有一个正确的列。

于 2013-06-03T06:41:16.787 回答