简体   繁体   中英

Handling radio buttons when applying to a nested form created dynamically

I have an app where users can create their own forms and then apply them to their own clients

The forms are created dynamically, meaning users can add as many questions they want, and each question has many choices (think of a survey structure).

So far so good, now I'm struggling when applying the forms, specifically getting the answers saved, persisted and showing properly when rendering the edit view.

When rendering the edit view, each question has their choices multiplied by how many questions/answers the answered_form has (I don't know exactly which of them, I am guessing here).

Answers are persisted to database, although each question has their choices multiplied, the selected answer is checked and is checked in the collection of the original answer. (answer one checked in the first 3 choices, answer two in the second 3 choices, answer three in the third 3 choices and answer four in the forth 3 choices)

I've read 2 similar questions here in SO, RoR nested attributes produces duplicates when edit , and Nested form update action producing duplicate results , but I already have the :id in strong parameters (you can see it in the code below).

I want to make myself clear here: creating the form, with nested question and nested choices is working perfectly fine, and also editing the created form. The struggle is when USING, ANSWERING or APPLYING it in the APP.

Code:

_form.html.erb:

<%= form_for [@child, @answered_form] do |f| %>

  <%= f.hidden_field :form_id %>
  <%= f.hidden_field :child_id %>

  <div class="answered_form">

  <h1><%= @form.f_title %></h1>
  <h3><%= @form.f_description %></h3>
  <br>
  <% questions = @form.questions %>
  <% i = 1 %>
  <% questions.each do |question| %>

    <%= i.to_s + ". " %><%= question.q_title %>
    <br />
    <% choices = question.choices %>

    <%= f.fields_for :answers do |a| %>

      <% choices.each do |choice| %>

        <%= a.radio_button :a_content, choice.c_description %> 
        <%= a.label :a_content, choice.c_description, :value => choice.c_description, class: 'no-margin' %>
        <br />

      <% end %>

    <% end %>

     <br />
     <% i += 1 %>
  <% end %>

</div>

<div class="text-center">
  <%= f.submit yield(:button_text), class: "btn btn-primary btn-lg" %>
</div>

<% end %>

answered_forms_controller.rb:

class AnsweredFormsController < ApplicationController
  before_action :correct_answered_form,  only: [:edit, :update, :destroy]

  def new
    @child = current_user.children.find(params[:child_id])
    @form = current_user.forms.find(params[:form_id])
    @answered_form = @child.answered_forms.new(form_id: params[:form_id])
    @answered_form.answers.build
  end

  def create
    @answered_form = AnsweredForm.create(answered_form_params)
    if @answered_form.save
      flash[:success] = "New survey " + @answered_form.form.f_title + " applied to patient!"
      redirect_to current_user.children.find(params[:child_id])
    else
      render 'new'
    end
  end

  def edit
    @child = current_user.children.find(params[:child_id])
    @form = current_user.forms.find(params[:form_id])
  end

  def update
    if @answered_form.update_attributes(answered_form_params)
      flash[:success] = "Survey updated!"
      redirect_to @answered_form.child
    else
      render 'edit'
    end
  end

  def show
  end

  def destroy
    @child = current_user.children.find(params[:child_id])
    @form = current_user.forms.find(params[:form_id])
    @answered_form.destroy
    redirect_to :back
  end

  private

    # Strong params for creating and updating forms
    def answered_form_params
      params.require(:answered_form).permit(:form_id, :child_id, answers_attributes: [:id, :a_content, :a_boolean, :_destroy, :choice_id])
    end

    # Confirms the correct answered_form
    def correct_answered_form
      @answered_form = AnsweredForm.find(params[:id])
    end

end

Logs: POST:

Started POST "/children/1-juan-gomez-pereira/answered_forms" for ::1 at 2016-07-08 11:55:01 -0400
Processing by AnsweredFormsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"hFrRfEwVG4XSkdbPwrohm1QEQ0FtE/as3sM2Fj3Av3reVHJxZBVKPeuAeD713H7gVyZn7eppnULDhLJQz+EBeg==", "answered_form"=>{"form_id"=>"1", "child_id"=>"1", "answers_attributes"=>{"0"=>{"a_content"=>"Bajo"}, "1"=>{"a_content"=>"Sí"}, "2"=>{"a_content"=>"Derecha"}, "3"=>{"a_content"=>"Pesado"}}}, "commit"=>"Aplicar", "child_id"=>"1-juan-gomez-pereira"}

PATCH:

Started PATCH "/children/1-juan-gomez-pereira/answered_forms/3" for ::1 at 2016-07-08 11:55:54 -0400
Processing by AnsweredFormsController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"oGdqgUR95HMkMff40Gq1zWar/CH64F0jsN3oRHT1q/H6acmMbH21yx0gWQnnDOq2ZYnYjX2aNs2tmmwChtQV8Q==", "answered_form"=>{"form_id"=>"1", "child_id"=>"1", "answers_attributes"=>{"0"=>{"a_content"=>"Bajo", "id"=>"9"}, "1"=>{"a_content"=>"Bajo", "id"=>"10"}, "2"=>{"a_content"=>"Bajo", "id"=>"11"}, "3"=>{"a_content"=>"Confuso", "id"=>"12"}, "4"=>{"a_content"=>"No", "id"=>"9"}, "5"=>{"a_content"=>"Sí", "id"=>"10"}, "6"=>{"a_content"=>"Confuso", "id"=>"11"}, "7"=>{"a_content"=>"Confuso", "id"=>"12"}, "8"=>{"a_content"=>"Confuso", "id"=>"9"}, "9"=>{"a_content"=>"Izquierda", "id"=>"10"}, "10"=>{"a_content"=>"Confuso", "id"=>"11"}, "11"=>{"a_content"=>"Izquierda", "id"=>"12"}, "12"=>{"a_content"=>"Liviano", "id"=>"9"}, "13"=>{"a_content"=>"Liviano", "id"=>"10"}, "14"=>{"a_content"=>"Pesado", "id"=>"11"}, "15"=>{"a_content"=>"Liviano", "id"=>"12"}}}, "commit"=>"Actualizar", "child_id"=>"1-juan-gomez-pereira", "id"=>"3"}

I noticed that when POST, the id for answer is not passed as a parameter. If I check the console, I can see that answer was created properly.

I think this line could be the problem

<% choices.each do |choice| %>

If you have built question.answers , you can iterate on them only using f.fields_for :answers and skip the above line. I assume choices are not much different from answers .

Please clear me if i am wrong.

So the problem was in this line of the code:

<%= f.fields_for :answers do |a| %>

fields_for helper generates fields for the entire collection of the object for whom your are calling it.

In this case, @answered_form had 4 answers after creating it, so when calling fields_for in edit, it was generating 4 fields set for each question.

To solve this, you need to specify a collection that fits your needs and pass it through the fields_for helper:

<%= f.fields_for :answers, ANSWERS_COLLECTION do |a| %>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM