0
votes

I'm writing a quiz app with rails 5. Users are presented with multiple choice questions from the database. For each question, the user can select either a single option (radio button) or multiple options (checkboxes). This is stored in the db as a boolean field 'multiselect'.

I'm using form_for to build the form.

<div class="answer-box">
      <% if m.object.multiselect %>
        <%= m.collection_check_boxes :answer, m.object.options, :id, :option_text, { checked: m.object.options.first.id } %>
      <% else %>
        <%= m.collection_radio_buttons :answer, m.object.options, :id, :option_text, { checked: m.object.options.first.id } %>
      <% end %>

      <%= m.hidden_field(:question_id, value: m.object.id) %>
      <%= m.hidden_field(:question_type, value: 'Mcq') %>
</div>

In the controller, I've permitted the params hash as follows :

def response_params
params.require(:quiz).permit(
  {
    mcq_responses_attributes: [
      :question_id,
      :question_type,
      answer: []
    ]
  })
end

The problem is when the question is multi-select, :answer is an array and when it is single-select, :answer is an integer. What I've done is check if :answer is an array and if not then convert the single integer to an array and then permit it using the above function.

def create_answer_array
  params[:quiz][:mcq_responses_attributes].each do |k, r|
    r[:answer] = Array(r[:answer]) unless r[:answer].is_a? Array
  end
end

Is there a better way to do this?

1

1 Answers

0
votes

It generally a good practice to treat the params and anything else from the request as immutable as far as possible.

Instead you can just check in your params sanitation method which of the two scenarios is applicable:

def response_params
  p = params.require(:quiz)
  if params[:quiz][:answer].is_a? Array
    p.permit(:question_id, :question_type, answer: [])
  else
    p.permit(:question_id, :question_type, :answer)
  end
end