1
votes

I'm working on deeply nested attributes and running into this unpermitted attributes error.

Log:

Started POST "/videos/1/quizzes"
Processing by QuizzesController#create as HTML
  Parameters: {"utf8"=>"✓", 
"authenticity_token"=>"XdJ5lPZ7QuVEZiVYbphnV0T/NpMMTKVaL2dcWRxHVQU=", 
"quiz"=>{"name"=>"Test",
"question"=>{"content"=>"Test", 
"answer"=>{"content"=>"Test"}}}, "commit"=>"Submit", "video_id"=>"1"}

 Video Load (0.1ms)  SELECT  "videos".* FROM "videos"  WHERE "videos"."id" = ? LIMIT 1  [["id", 1]]

 Unpermitted parameters: question

So all the data is being submitted. From reading around it looks like the nested question parameters is supposed to be "question_attributes"=> But in my log it just shows "question"=>. I don't know if that has something to do with it? But at this point it's really my only idea.

quizzes#new:

def new
  @video = Video.find(params[:video_id])
  @quiz = @video.build_quiz
  @quiz.questions.build
  @quiz.questions.each do |question|
     question.answers.build
  end
end

The video_id params is working and as you can see above it is being submitted.

quizzes#create

def create
  @video = Video.find(params[:video_id])
  @quiz = @video.create_quiz(quiz_params)
  respond_to do |format|
    if @quiz.save
        format.html { redirect_to @quiz, notice: 'quiz was successfully created.' }
        format.json { render :show, status: :created, location: @quiz }
     else
        format.html { render :new }
        format.json { render json: @quiz.errors, status: :unprocessable_entity }
    end
  end
end

quizzes_params

def quiz_params
   params.require(:quiz).permit(:name, questions_attributes: [:id, :content, :quiz_id, answers_attributes: [:id, :content, :question_id]])
end

So as you can see it's stopping the question parameters and the answer parameters from being saved.

Let me know if you need anything else! Thank you in advance for any help!

Update Here is the form partial! I also tried doing form_for @quiz do |f| but that didn't change what was submitted. The other thing I tried was pluarlizing :question and :answer as :questions and :answers but no luck.

  <%= form_for [@video, @quiz] do |f| %>
    <%= f.label :name, "Title" %>
    <%= f.text_field :name %>

    <%= f.fields_for :question do |questions| %>
      <%= questions.label :content, "Question" %><br>
      <%= questions.text_area :content, rows: 3  %>

      <%= questions.fields_for :answer do |answers| %>
        <%= answers.label :content, "Answer" %>
        <%= answers.text_field :content %>
      <% end  %>

    <% end %>
    <%= f.submit "Submit" %>

  <% end %>
1
You need to check the parameters structure on your view from where you are submitting the form.Bharat soni
your html file please, I think you must be missing something, like f.fields_for was written as fields_for, that's why your "question_attributes" has become "question"argentum47
Ok, I added the form partial.Jacksonvoice
OP deserves a medal for showing in a real life example of how to permit deeply-nested attributes with strong parameters. The examples here on SO, the Rails-documentation and on GitHub were all about one object's attribute nested into another's. Nobody has been talking about nesting three into one another. I've been scratching my head for hours!ljnissen

1 Answers

0
votes

Solution:

I changed this line in the quizzes_controller from @quiz.questions.build to 2.times { @quiz.questions.build } and it fixed the issue. Not really sure why it works now, but it does. Any explanation as to why would be really appreciated!

def new
    @video = Video.find(params[:video_id])
    @quiz = @video.build_quiz
    2.times { @quiz.questions.build }
    @quiz.questions.each do |question|
        question.answers.build
    end
end