Search code examples
formshidden-fieldruby-on-rails-6

How do you populate a hidden field in a Rails 6 form that loops through one table and stores answers in another table?


I am trying to create a personality test.

I have a Questions table that looks like this


       ID  | Question      |
    ----------------------------
        1  | How likely would you etc... 


and a Results table that looks like this

       ID  | Answer      | Question_ID | User_Id
    ------------------------------------------------
        1  |  1          |  1          |   1

I have 68 questions that I want to loop through and I want to store the answers (which are integers on a scale from 1-10) in my Results table.

How do I create a form that will save data to my Results table?

I am having trouble populating the answer column of my Results table.

Here's what I have. It doesn't work.

<%= form_with(model: @result, local: true) do |form| %>
  <% @questions.each do |question| %> 
    <div>
      <h4><%= question.id %>. <%=question.question %></h4><br /> 
      <div class="hidden-field">
        <%= form.hidden_field :question_id, value: question.id %>
      </div>
      <div class="field">
        <%= form.number_field :answer, placeholder:'Please answer on a scale from 1 to 10' %>
      </div>
    </div> 
  <% end %>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

In my controller, I have a Home Controller (to display a home page)

class HomeController < ApplicationController
  def index 
      @questions = Question.all.order(:created_at)
      @user = User.new
      @result = Result.new
  end
end

I also have my Results Controller

class ResultsController < ApplicationController
  before_action :set_result, only: [:show, :edit, :update, :destroy]

  def new
    @result = Result.new
  end

  def create
    @result = Result.new(result_params)
  end

  private
    def set_result
      @result = Result.find(params[:id])
    end

    def result_params
      params.require(:result).permit(:answer, :user_id, :question_id)
    end
end

The questions are displaying perfectly fine. I can even store the data, but only one record gets saved and it only populates the question_id column with 68 and leaves the answer column NULL

What am I doing wrong?


Solution

  • So after reading up on this, I have code that works. This post helped tremendously along with @chiperific reply

    I put this form in my results/new.html.erb file

        <%= form_with(model: result, local: true) do |form| %>
          <% @questions.each do |question| %> 
            <%= fields_for "result[]", result do |result_field| %>
              <h4><%= question.id %>. <%=question.question %></h4><br /> 
               <%= result_field.hidden_field :question_id, value: question.id %>
               <%= result_field.number_field :answer, placeholder:'Please answer on 
                a scale from 1 to 10' %>
            <% end %>
          <% end %>
          <div class="actions">
            <%= form.submit %>
          </div>
       <% end %>
    

    I put this in my results controller

    class ResultsController < ApplicationController
      before_action :set_result, only: [:show, :edit, :update, :destroy]
    
      def new
        @result = Result.new
        @questions = Question.all.order(:created_at)
      end
    
      def create
        params[:result].each do |result_param|
         result = Result.new(result_param.permit(:answer, :user_id, :question_id))
        end
      end
    
      private
        def set_result
          @result = Result.find(params[:id])
        end
    end
    

    The key insight was that I need to loop through my results and create a new result instance for every single one of my results.

    I removed my Home controller and home view page and changed my routes.rb file to root 'results#new'

    I have not addressed the issues of duplicate records (which is very valid) so I know my code will need some refactoring, but this code answers my initial question (I'm very open to feedback)