检查任何嵌套属性是否包含值的验证

Validation that checks if any nested attributes contain a value

我正在尝试编写一个验证来检查属于某个模型的嵌套属性之一是否包含特定值。

在这种情况下,我有一个包含许多答案的问题模型。我需要一个验证来检查是否至少有一个问题标记了正确答案。

这是一个用于创建测试的应用程序。这个问题有几个答案,但并非所有答案都是正确的。

这是我的问题模型:

class Question < ApplicationRecord
    belongs_to :examination
    has_many :answers, dependent: :destroy
    has_many :responses

    accepts_nested_attributes_for :answers, allow_destroy: true, :reject_if => :all_blank

    validates_presence_of :body
    validates_presence_of :question_type

    validate :has_correct_ans?

     private

     def has_correct_ans?
      errors.add(:correct, "You must select at least one correct answer") unless
      self.answers.exists?(correct: true)
     end
end

这是答案模型

class Answer < ApplicationRecord
    belongs_to :question
    has_many :responses, dependent: :destroy

end

我试图编写一个名为 "has_correct_ans?" 的方法来检查是否有任何答案包含正确的属性。但这每次都失败了。我假设那是因为在保存数据之前数据库中不存在。通过在控制台中测试该命令对现有数据运行良好。
Question.find.answers.exists?(correct: true)

对于其中一个答案具有正确属性的问题 return 为真。

我真的很喜欢这个作为验证。我只是不知道如何在保存之前访问嵌套属性。

这是参数的样子:

Parameters: {"utf8"=>"✓", "authenticity_token"=>"dOf8H1Wqark3TZAGgX6kaY5Yt4kYKm1FNbCnNi4BlVTTQV9PijlkA1bNS8Qi8DwLLxV6FkWzNbmiT6X+7Vr6Xg==", "question"=>{"body"=>"gfdgdfs", "question_type"=>"Multiple Choice", "points"=>"1", "answers_attributes"=>{"0"=>{"correct"=>"true", "body"=>"dggf", "_destroy"=>"0"}}}, "commit"=>"Submit", "examination_id"=>"12"}

我也尝试使用参数在控制器中执行此操作。这是我的创建函数的样子:

class QuestionsController < ApplicationController

  def create
    @exam = Examination.find(params[:examination_id])
    @question = @exam.questions.build(question_params)
    ans_params = params[:question][:answers_attributes]
    @correct_ans = false
    ans_params.each do |k, v|
      if @correct_ans == false
       @correct_ans =  v.has_key?(:correct)
      end
    end

    if @exam.questions.count > 0
      @question.position = @exam.questions.count + 1 
    else 
      @question.position = 1
    end
    if @correct_ans == true && @question.save
      redirect_to @exam, notice: "question created successfully"
    elsif @question.save
      flash[:error] = "You need a correct answer"
      render :new
    else
      render :new
    end
  end

这实际上也不起作用。即使没有正确答案,它仍然保存。无论如何,我不想在控制器中这样做。作为验证,它会更好地工作。

我确定我在这里遗漏了一些明显的东西。谁能帮帮我?

我明白了!

谢谢,阿希克。我不知道你可以使用这样的方法,即使数据不在数据库中。

我试过你的想法。它没有 return 正确的结果,但非常接近。

answers.map{ |x| x[:correct] == true }.size == 0?

Returns 所有答案记录的正确属性数组。像这样:

[false, false, true]

我把方法稍微改成这样:

answers.map{ |x| x[:correct]}.include? true

如果任何记录包含正确的,则 return 为真。我在我的验证方法中尝试过它并且它完美地工作。

这是更新后的问题模型。

class Question < ApplicationRecord
    belongs_to :examination
    has_many :answers, dependent: :destroy
    has_many :responses

    accepts_nested_attributes_for :answers, allow_destroy: true, :reject_if => :all_blank

    validates_presence_of :body
    validates_presence_of :question_type

    validate :has_correct_ans?

     private

     def has_correct_ans?
      errors.add(:correct, "You must select at least one correct answer") unless
      answers.map{ |x| x[:correct]}.include? true

     end
end