【问题标题】:Rails nested forms building quizRails 嵌套表单构建测验
【发布时间】:2022-06-10 18:11:58
【问题描述】:

我正在构建一个测验并使用嵌套表单来提交答案。我想我正在研究如何提交嵌套表单数组?

我有以下设置:

测验

has_many :quiz_answers, dependent: :destroy
accepts_nested_attributes_for :quiz_answers, allow_destroy: true

测验答案

belongs_to :quiz, optional: true

接下来的两个创建由管理员设置的测验问题和选项(即 a、b、c、d)。这允许根据需要即时添加和取出问题。这部分工作正常,我在这里没有问题。

测验问题

has_many :quiz_options, dependent: :destroy
accepts_nested_attributes_for :quiz_options, allow_destroy: true

测验选项

belongs_to :quiz_question, optional: true

我遇到的这个问题是当用户开始测验时,我如何遍历每个问题并让用户提交一个选项,单击下一步并继续下一个问题,直到全部完成?到目前为止,我认为它正在为数据库保存一个答案,但它列出了所有问题:

class QuizzesController < ApplicationController
 def new
    @quiz = Quiz.new
    @quiz_question = QuizQuestion.where(active: true)
    @quiz.quiz_answers.build
  end
 
def create
    @quiz = Quiz.new(quiz_params)
   
    respond_to do |format|
      if @quiz.save
        format.html { redirect_to quiz_url(@quiz), notice: "Quiz was successfully created." }
        format.json { render :show, status: :created, location: @quiz }
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @quiz.errors, status: :unprocessable_entity }
      end
    end
  end
end

表格

<%= form_with(model: quiz) do |form| %>
 <%= form.fields_for :quiz_answers do |builder| %>
  <%= render 'quiz_answer', form: builder %>
 <% end %>
 <%= form.submit "Submit", class: 'btn btn-primary' %>
<% end %>

部分

<% @quiz.each do |question| %>
 <h2><%= question.question %></h2>
  <% question.quiz_options.each do |o| %>
   <%= form.radio_button :answer, o.answer %> <%= o.answer %>
  <% end %>
<% end %>

总而言之,我想知道问题 1、用户提交答案、问题 2、用户提交答案等是否可以在嵌套表单环境中全部来自预先确定的问题和答案?

【问题讨论】:

    标签: ruby-on-rails


    【解决方案1】:

    您可以在下面的代码中执行此操作:

    我想您的quiz_answers 表中有quiz_option_id 列,如果没有,则必须将其添加到表中

    add_reference :quiz_answers, :quiz_option, null: false, 
    
    # controllers/quizzes_controller.rb
    
    class QuizzesController < ApplicationController
      def new
        @quiz = Quiz.new
        @quiz_questions = QuizQuestion.where(active: true)
        @quiz_questions.each.with_index do |question, i|
          @quiz.quiz_answers.build(quiz_question_id: question.id, is_current: i.zero?)
        end
      end
    
      def create
        @quiz = Quiz.new(quiz_params)
    
        respond_to do |format|
          if @quiz.valid?
            if @quiz.quiz_answers.all?(&-> (answer) { answer.quiz_option_id.present? })
              @quiz.save
              format.html { redirect_to quiz_url(@quiz), notice: "Quiz was successfully created." }
              format.json { render :show, status: :created, location: @quiz }
            else
              new_current = @quiz.quiz_answers.detect(&-> (answer) { !ActiveModel::Type::Boolean.new.cast(answer.is_current) && answer.quiz_option_id.blank? })
              current_active = @quiz.quiz_answers.detect(&-> (answer) { ActiveModel::Type::Boolean.new.cast(answer.is_current) })
              current_active.is_current = false
              new_current.is_current = true
    
              format.html { render :new, status: :unprocessable_entity }
              format.json { render json: @quiz.errors, status: :unprocessable_entity }
            end
          else
            format.html { render :new, status: :unprocessable_entity }
            format.json { render json: @quiz.errors, status: :unprocessable_entity }
          end
        end
      end
    
      private
    
      def quiz_params
        params.require(:quiz).permit(quiz_answers_attributes: %i[is_current quiz_question_id quiz_option_id])
      end
    end
    
    # models/quiz_answer.rb
    
    class QuizAnswer < ApplicationRecord
      attr_accessor :quiz_question_id, :is_current
    
      belongs_to :quiz, optional: true
      belongs_to :quiz_option, optional: true
    
      validates :quiz_option_id, presence: true, if: -> { ActiveModel::Type::Boolean.new.cast(is_current) }
    
      def quiz_question
        @quiz_question ||= QuizQuestion.find_by(id: quiz_question_id)
      end
    end
    

    d-none 来自 Bootstrap 或者您可以定义自己的

    .d-none {
      display: none;
    }
    
    # views/quizzes/_quiz_answer.html.erb
    
    <div class="<%= ActiveModel::Type::Boolean.new.cast(form.object.is_current) ? "" : "d-none" %>">
      <h2><%= form.object.quiz_question.question %></h2>
      <%= form.hidden_field :quiz_question_id %>
      <%= form.hidden_field :is_current %>
      <%= form.collection_radio_buttons :quiz_option_id, form.object.quiz_question.quiz_options, :id, :answer %>
      <%= form.object.errors.full_messages.first %>
      <br/>
    </div>
    

    另外我想在new.html.erb 你有一些文件:

    # views/quizzes/new.html.erb
    
    <%= render "form", quiz: @quiz %>
    

    如果您有任何问题,请随时提出

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-21
      • 1970-01-01
      相关资源
      最近更新 更多