【问题标题】:Rails custom attribute validation not allowing creation of new objectRails 自定义属性验证不允许创建新对象
【发布时间】:2013-06-03 14:43:50
【问题描述】:

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

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

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

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

answer.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 %>'> ✓</div>
        <% end %>
    <% end %>
</div>

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3 validation


    【解决方案1】:

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

    validate :one_correct_answer, if: :correct?
    

    这样,方法 one_correct_answer 仅在当前答案正确时才会被验证。

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

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

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

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

    【讨论】:

      【解决方案2】:

      你的问题可能在这里:

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

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

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

      我会使用这个条件:

      self.question.answers.count(&:correct) <= 1
      

      【讨论】:

        猜你喜欢
        • 2013-08-20
        • 2023-04-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-06-12
        相关资源
        最近更新 更多