auto
auto

Reputation: 1173

Unpermitted Parameter error in Rails for nested nested form submission

I'm trying to create a quiz builder where a user builds a quiz that is added to the Quiz model, a question that is in the QuizQuestions model and answer choices in and AnswerChoices model.

The Quiz is the main controller. From the edit page, the user can add a new question and select an answer choice type The question model is nested under the quiz model. Then the answer model is nested under the quiz model.

However, saving the form does not save the answer choices to the database, and there is an unpermitted parameter message, but all parameters are permitted, and it happens even with one paramter.

The controller looks like:

def edit
        @quiz = Quiz.find(params[:id])

        @quiz_questions = @quiz.quiz_questions.all 
        
        @quiz.quiz_questions.build(quiz_params) unless @quiz.quiz_questions.present?

    end

    def update
        @quiz = Quiz.find(params[:id])
        @quiz_questions = @quiz.quiz_questions

        if @quiz.update(quiz_params)
            redirect_to edit_quiz_path, notice: "Successfully upated quiz"
        else
           redirect_to admin_path,  notice: "UNSUCCESSFULLY added quiz"
        
        end

    end
def quiz_params
    params.require(:quiz).permit(
        :quiz_name,
         quiz_questions_attributes: [:id, :question, :quiz_id],
         quiz_answers_attributes: [:id, :question_id]
         
    
    )
end

The models (in different files):

class Quiz < ApplicationRecord

    #Associations
    has_many :quiz_questions, foreign_key: :quiz_id
    accepts_nested_attributes_for :quiz_questions

end

class QuizQuestion < ApplicationRecord


    #ASSOCIATIONS
    belongs_to :quiz, foreign_key: :quiz_id

    has_many :quiz_answers, foreign_key: :question_id

    accepts_nested_attributes_for :quiz_answers, allow_destroy: true

end

class QuizAnswer < ApplicationRecord

    #Associations
        belongs_to :quiz_question, foreign_key: :question_id
        
end

quiz/edit.html.erb

<div >
        <%= form_with model: @quiz do |newQuiz| %>

        <div >

              <h3> <%= newQuiz.label :quiz_name, "QUIZ: " %></h3>

              <%= newQuiz.text_field :quiz_name, %>
            
        </div>
                               

        <%= newQuiz.fields_for :quiz_questions do |questionData| %>

                    
            <div>
                <h3> <%= questionData.label :question, "Question" %></h3>
                <%= questionData.text_field :question %>
            </div>


            <%= questionData.hidden_field :quiz_id, value: 1 %>


            <%= newQuiz.fields_for :quiz_answers do |answerData| %>

                <%= answerData.text_field :id %>


                <%= answerData.hidden_field :question_id, value: 1 %>
                
            
             <% end %>
                   
        <% end %>
                

    </div>
        <%= newQuiz.submit "SAVE" %>
    <% end %>
</div>

The error says:

Unpermitted parameter: :quiz_answers. Context: { controller: QuizzesController, action: update, request: #<ActionDispatch::Request:...>, params: {"_method"=>"patch", "authenticity_token"=>"[FILTERED]", "quiz"=>{"quiz_name"=>"Test Quiz 1", "quiz_questions_attributes"=>{"0"=>{"question"=>"This is a test question?", "quiz_id" => "1", "id"=>"1"}}, "quiz_answers"=>{"id"=>"1", "question_id"=>"1"}}, "commit"=>"SAVE", "controller"=>"quizzes", "action"=>"update", "id"=>"1"} }

Upvotes: 1

Views: 41

Answers (1)

Benjamin Scharbau
Benjamin Scharbau

Reputation: 2089

Basically you are nesting your models in 3 levels (A Quiz contains multiple QuizQuestions, and a QuizQuestion contains multiple QuizAnswers.

So to use the accepts_nested_attributes option, your input parameters should also be nested accordingly, e.g. your quiz_params are supposed to look like

def quiz_params
    params.require(:quiz).permit(
        :quiz_name,
         quiz_questions_attributes: [
           :id,
           :question,
           :quiz_id,
           quiz_answers_attributes: [:id, :question_id]
        ],
    )
end

The view should be build accordingly, that you have some input fields for the answers for every single question the user enters, e.g.

<div>
  <%= form_with model: @quiz do |newQuiz| %>
    <div>
      <h3> <%= newQuiz.label :quiz_name, "QUIZ: " %></h3>
      <%= newQuiz.text_field :quiz_name, %>
    </div>

    <%= newQuiz.fields_for :quiz_questions do |questionData| %>
      <div>
        <h3> <%= questionData.label :question, "Question" %></h3>
        <%= questionData.text_field :question %>
      </div>
      <%= questionData.hidden_field :quiz_id, value: 1 %>
      
      <%= questionData.fields_for :quiz_answers do |answerData| %>
        <%= answerData.text_field :id %>
        <%= answerData.hidden_field :question_id, value: 1 %>
      <% end %>
    <% end %>
    <%= newQuiz.submit "SAVE" %>
  <% end %>
</div>

On a sidenote, you should work a bit of your formatting, you are actually closing one div more than you are opening, which is a bit difficult to spot in the code as you wrote it...

Upvotes: 1

Related Questions