refactor quiz processing

completes #60
This commit is contained in:
Mark Moser 2016-09-02 17:51:35 -05:00
parent 3f8d089701
commit a977c0ceb3
10 changed files with 62 additions and 87 deletions

View File

@ -54,7 +54,7 @@ guard 'livereload' do
watch(%r{config/locales/.+\.yml}) watch(%r{config/locales/.+\.yml})
end end
guard :minitest, spring: "bin/rails test" do # all_after_pass: true guard :minitest, spring: "bin/rails test", all_after_pass: true do
watch(%r{^app/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" } watch(%r{^app/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" }
watch(%r{^app/controllers/(admin|application)_controller\.rb$}) { 'test/controllers' } watch(%r{^app/controllers/(admin|application)_controller\.rb$}) { 'test/controllers' }
watch(%r{^app/controllers/(.+)_controller\.rb$}) { |m| "test/integration/#{m[1]}_test.rb" } watch(%r{^app/controllers/(.+)_controller\.rb$}) { |m| "test/integration/#{m[1]}_test.rb" }
@ -71,7 +71,7 @@ end
# ESLint # ESLint
guard :shell, all_on_start: true do guard :shell, all_on_start: true do
watch %r{app/assets/javascripts/*/.*} do |file| watch %r{app/assets/javascripts/*/.*} do |file|
system %(echo "ESLinting \033[32m#{file[0]}\033[0m") system %(echo "ESLint:\033[32m #{file[0]}\033[0m")
system %(eslint #{file[0]}) system %(eslint #{file[0]})
end end
end end

View File

@ -12,7 +12,8 @@ class QuizController < ApplicationController
def update_answer def update_answer
@answer = prep_answer answer_params[:question_id] @answer = prep_answer answer_params[:question_id]
prep_status prep_status
send "process_#{prep_question(answer_params[:question_id]).input_type}" prep_question(answer_params[:question_id])
@answer.update(process_answer_params)
route_answer_xhr and return if request.xhr? route_answer_xhr and return if request.xhr?
route_answer_html route_answer_html
end end
@ -48,14 +49,23 @@ class QuizController < ApplicationController
params.require(:answer).permit( params.require(:answer).permit(
:question_id, :question_id,
:answer_id, :answer_id,
:radio, :answer,
:text, answer_array: [],
checkbox: [], answer_hash: [:later, :html, :css, :js, :text, :other, options: []]
with_other: [:other, options: []],
live_code: [:later, :html, :css, :js, :text]
) )
end end
def process_answer_params
answer = answer_params
answer[:saved] = params.key?(:save)
answer[:submitted] = params.key?(:submit)
answer[:answer] = answer_params[:answer_array] unless answer_params[:answer_array].nil?
answer[:answer] = answer_params[:answer_hash].to_h unless answer_params[:answer_hash].nil?
answer.delete(:answer_array)
answer.delete(:answer_hash)
answer
end
def prep_answer qid = answer_params[:question_id] def prep_answer qid = answer_params[:question_id]
answer_ids = { question_id: qid, candidate_id: current_candidate.to_i } answer_ids = { question_id: qid, candidate_id: current_candidate.to_i }
answer = Answer.find_or_create_by(answer_ids) answer = Answer.find_or_create_by(answer_ids)
@ -68,7 +78,6 @@ class QuizController < ApplicationController
flash[:error] = answer_params[:question_id].to_i flash[:error] = answer_params[:question_id].to_i
render :question render :question
else else
# TODO: change params.key? to submit = save/next/summary
redirect_to :saved and return if params.key?(:save) redirect_to :saved and return if params.key?(:save)
redirect_to :question redirect_to :question
end end
@ -86,36 +95,4 @@ class QuizController < ApplicationController
render json: results.to_json render json: results.to_json
end end
end end
# TODO: maybe a better way to do this. See Admin/QuestionController#process_question_params
def process_text
@answer.update(answer: answer_params[:text],
saved: params.key?(:save),
submitted: params.key?(:submit))
end
def process_radio
@answer.update(answer: answer_params[:radio],
saved: params.key?(:save),
submitted: params.key?(:submit))
end
def process_checkbox
@answer.update(answer: answer_params[:checkbox],
saved: params.key?(:save),
submitted: params.key?(:submit))
end
def process_live_code
@answer.update(answer: answer_params[:live_code].to_h,
saved: params.key?(:save),
submitted: params.key?(:submit))
end
def process_radio_other
@answer.update(answer: answer_params[:with_other].to_h,
saved: params.key?(:save),
submitted: params.key?(:submit))
end
alias process_checkbox_other process_radio_other
end end

View File

@ -1,18 +1,15 @@
<% question.input_options.each_with_index do | option, i | <% answers = Array(question.answer) %>
option_id = "#{question.question_id}_#{i}" <%= form.collection_check_boxes(:answer_array, question.input_options, :to_s, :to_s, {}, {class: 'checkbox'}) do | option | %>
<%
option_id = "#{question.question_id}#{sanitize_to_id(option.value)}"
checked = answers.include?(option.value) ? 'checked' : ''
%>
checkbox_html = {class: 'checkbox',
id: "answer_#{option_id}",
name: "answer[checkbox][]",
checked: Array(question.answer).include?(option),
data: { last: Array(question.answer).include?(option) ? 'checked' : '' }
}
answers = answer.try(:answer) || answer
%>
<div class="form-group-multiples"> <div class="form-group-multiples">
<%= form.check_box(:answer, checkbox_html, option, '') %> <%= option.check_box( id: option_id, checked: checked, data: { last: checked } ) %>
<%= form.label(option_id, option) %> <%= option.label(for: option_id) %>
</div> </div>
<% end %> <% end %>
<%= render partial: "quiz/answer_errors", locals: {question: question, answer: answer} %> <%= render partial: "quiz/answer_errors", locals: {question: question, answer: answer} %>

View File

@ -7,7 +7,7 @@
checkbox_html = {class: 'checkbox', id: option_id, data: { last: answers.include?(option) ? 'checked' : '' } } checkbox_html = {class: 'checkbox', id: option_id, data: { last: answers.include?(option) ? 'checked' : '' } }
%> %>
<div class="form-group-multiples"> <div class="form-group-multiples">
<%= check_box_tag('answer[with_other][options][]', option, answers.include?(option), checkbox_html) %> <%= check_box_tag('answer[answer_hash][options][]', option, answers.include?(option), checkbox_html) %>
<%= label_tag(option_id, option) %> <%= label_tag(option_id, option) %>
</div> </div>
<% <%
@ -19,9 +19,9 @@
checkbox_html = {class: 'checkbox', id: option_id, data: { last: answers.include?('other') ? 'checked' : '' } } checkbox_html = {class: 'checkbox', id: option_id, data: { last: answers.include?('other') ? 'checked' : '' } }
text_html = {class: 'input-other', id: "text_#{option_id}", data: { last: other_value }} text_html = {class: 'input-other', id: "text_#{option_id}", data: { last: other_value }}
%> %>
<%= check_box_tag('answer[with_other][options][]', 'other', answers.include?('other'), checkbox_html) %> <%= check_box_tag('answer[answer_hash][options][]', 'other', answers.include?('other'), checkbox_html) %>
<%= label_tag(option_id, 'Other') %> <%= label_tag(option_id, 'Other') %>
<%= text_field_tag 'answer[with_other][other]', other_value, text_html %> <%= text_field_tag 'answer[answer_hash][other]', other_value, text_html %>
</div> </div>
<%= render partial: "quiz/answer_errors", locals: {question: question, answer: answer} %> <%= render partial: "quiz/answer_errors", locals: {question: question, answer: answer} %>

View File

@ -42,22 +42,22 @@
</div> </div>
<div id="answer<%= question.question_id %>" data-id="live-coder-answer" style="display: none;"> <div id="answer<%= question.question_id %>" data-id="live-coder-answer" style="display: none;">
<label for="answer_live_code_text">Enter answer here</label> <label for="answer_answer_hash_text">Enter answer here</label>
<%= text_area_tag 'answer[live_code][text]', value_text, { disabled: true, data: {last: answers['text']}} %> <%= text_area_tag 'answer[answer_hash][text]', value_text, { disabled: true, data: {last: answers['text']}} %>
<div class="code-input"> <div class="code-input">
<label for="answer_live_code_html">HTML</label> <label for="answer_answer_hash_html">HTML</label>
<%= text_area_tag 'answer[live_code][html]', value_html, { disabled: true, data: {id: 'code-html', last: answers['html']}, class: 'code-answer code-html' } %> <%= text_area_tag 'answer[answer_hash][html]', value_html, { disabled: true, data: {id: 'code-html', last: answers['html']}, class: 'code-answer code-html' } %>
</div> </div>
<div class="code-input"> <div class="code-input">
<label for="answer_live_code_css">CSS</label> <label for="answer_answer_hash_css">CSS</label>
<%= text_area_tag 'answer[live_code][css]', value_css, { disabled: true, data: {id: 'code-css', last: answers['css']}, class: 'code-answer code-css' } %> <%= text_area_tag 'answer[answer_hash][css]', value_css, { disabled: true, data: {id: 'code-css', last: answers['css']}, class: 'code-answer code-css' } %>
</div> </div>
<div class="code-input"> <div class="code-input">
<label for="answer_live_code_js">JS</label> <label for="answer_answer_hash_js">JS</label>
<%= text_area_tag 'answer[live_code][js]', value_js, { disabled: true, data: {id: 'code-js', last: answers['js']}, class: 'code-answer code-js' } %> <%= text_area_tag 'answer[answer_hash][js]', value_js, { disabled: true, data: {id: 'code-js', last: answers['js']}, class: 'code-answer code-js' } %>
</div> </div>
<div class="results" data-id="results"></div> <div class="results" data-id="results"></div>

View File

@ -1,12 +1,15 @@
<% question.input_options.each do | option | <% answer = answer.try(:answer) || answer %>
option_id = "#{option.parameterize}_#{question.to_i}" <%= form.collection_radio_buttons(:answer, question.input_options, :to_s, :to_s, {}, {class: 'radio'}) do | option | %>
radio_html = {class: 'radio', id: option_id, data: {last: (question.answer == option) ? 'checked' : '' }} <%
answers = answer.try(:answer) || answer option_id = "#{question.question_id}#{sanitize_to_id(option.value)}"
%> checked = answer == option.value ? 'checked' : ''
%>
<div class="form-group-multiples"> <div class="form-group-multiples">
<%= radio_button_tag('answer[radio]', option, (question.answer == option), radio_html) %> <%= option.radio_button( id: option_id, checked: checked, data: { last: checked } ) %>
<%= label_tag(option_id, option) %> <%= option.label(for: option_id) %>
</div> </div>
<% end %> <% end %>
<%= render partial: "quiz/answer_errors", locals: {question: question, answer: answer} %> <%= render partial: "quiz/answer_errors", locals: {question: question, answer: answer} %>

View File

@ -7,7 +7,7 @@
radio_html = {class: 'radio', id: option_id, data: {last: (answer == option) ? 'checked' : '' }} radio_html = {class: 'radio', id: option_id, data: {last: (answer == option) ? 'checked' : '' }}
%> %>
<div class="form-group-multiples"> <div class="form-group-multiples">
<%= radio_button_tag('answer[with_other][options][]', option, (answer == option), radio_html) %> <%= radio_button_tag('answer[answer_hash][options][]', option, (answer == option), radio_html) %>
<%= label_tag(option_id, option) %> <%= label_tag(option_id, option) %>
</div> </div>
<% <%
@ -19,9 +19,9 @@
radio_html = {class: 'radio', id: option_id, data: { last: answer }} radio_html = {class: 'radio', id: option_id, data: { last: answer }}
text_html = {class: 'input-other', id: "text_#{option_id}", data: { last: other_value }} text_html = {class: 'input-other', id: "text_#{option_id}", data: { last: other_value }}
%> %>
<%= radio_button_tag('answer[with_other][options][]', 'other', (answer == 'other'), radio_html) %> <%= radio_button_tag('answer[answer_hash][options][]', 'other', (answer == 'other'), radio_html) %>
<%= label_tag option_id, 'Other' %> <%= label_tag option_id, 'Other' %>
<%= text_field_tag 'answer[with_other][other]', other_value, text_html %> <%= text_field_tag 'answer[answer_hash][other]', other_value, text_html %>
</div> </div>
<%= render partial: "quiz/answer_errors", locals: {question: question, answer: answer} %> <%= render partial: "quiz/answer_errors", locals: {question: question, answer: answer} %>

View File

@ -1,9 +1,7 @@
<% <% answer = answer.respond_to?(:answer) ? answer.answer : answer %>
answers = answer.respond_to?(:answer) ? answer.answer : answer
%>
<label for="answer_text">Enter answer here</label> <label for="answer_answer">Enter answer here</label>
<%= text_area_tag 'answer[text]', answers, {rows: 10, data: { last: answers } } %> <%= text_area_tag 'answer[answer]', answer, {rows: 10, data: { last: answer } } %>
<div class="chars <%= params[:action] == 'summary' ? 'hidden' : '' %>">Characters remaining: <span></span></div> <div class="chars <%= params[:action] == 'summary' ? 'hidden' : '' %>">Characters remaining: <span></span></div>

View File

@ -24,7 +24,7 @@ class QuizControllerTest < ActionDispatch::IntegrationTest
test "should redirect to saved on save" do test "should redirect to saved on save" do
setup_auth candidates(:dawn) setup_auth candidates(:dawn)
qid = questions(:fed5).id qid = questions(:fed5).id
post post_answer_path, params: { save: 'Save', answer: { question_id: qid, radio: 'an option' } } post post_answer_path, params: { save: 'Save', answer: { question_id: qid, answer: 'an option' } }
assert_redirected_to saved_path assert_redirected_to saved_path
assert session[:test_id].present? assert session[:test_id].present?
@ -33,7 +33,7 @@ class QuizControllerTest < ActionDispatch::IntegrationTest
test "should redirect to next question on next" do test "should redirect to next question on next" do
setup_auth candidates(:roy) setup_auth candidates(:roy)
qid = questions(:fed3).id qid = questions(:fed3).id
params = { submit: 'Next', answer: { question_id: qid, live_code: { text: 'stuff' } } } params = { submit: 'Next', answer: { question_id: qid, answer_hash: { text: 'stuff' } } }
post post_answer_path, params: params post post_answer_path, params: params
assert_redirected_to question_path assert_redirected_to question_path
@ -61,7 +61,7 @@ class QuizControllerTest < ActionDispatch::IntegrationTest
test "should get flash message on bad radio response" do test "should get flash message on bad radio response" do
setup_auth candidates(:dawn) setup_auth candidates(:dawn)
qid = questions(:fed5).id qid = questions(:fed5).id
post post_answer_path, params: { answer: { question_id: qid, radio: nil } } post post_answer_path, params: { answer: { question_id: qid, answer: nil } }
assert_response :success assert_response :success
assert session[:test_id].present? assert session[:test_id].present?
@ -73,7 +73,7 @@ class QuizControllerTest < ActionDispatch::IntegrationTest
test "should get flash message on bad text response" do test "should get flash message on bad text response" do
setup_auth candidates(:dawn) setup_auth candidates(:dawn)
qid = questions(:fed4).id qid = questions(:fed4).id
post post_answer_path, params: { answer: { question_id: qid, text: nil } } post post_answer_path, params: { answer: { question_id: qid, answer: nil } }
assert_response :success assert_response :success
assert session[:test_id].present? assert session[:test_id].present?
@ -85,7 +85,7 @@ class QuizControllerTest < ActionDispatch::IntegrationTest
test "should process checkbox" do test "should process checkbox" do
setup_auth candidates(:dawn) setup_auth candidates(:dawn)
qid = questions(:fed10).id qid = questions(:fed10).id
post post_answer_path, params: { answer: { question_id: qid, checkbox: 'an-option' } } post post_answer_path, params: { answer: { question_id: qid, answer_array: 'an-option' } }
assert_response :success assert_response :success
assert session[:test_id].present? assert session[:test_id].present?
@ -96,7 +96,7 @@ class QuizControllerTest < ActionDispatch::IntegrationTest
test 'should handle XHR update and complete progress' do test 'should handle XHR update and complete progress' do
setup_auth candidates(:peggy) setup_auth candidates(:peggy)
qid = questions(:fed10).id qid = questions(:fed10).id
post post_answer_path, xhr: true, params: { answer: { question_id: qid, checkbox: ['an-option'] } } post post_answer_path, xhr: true, params: { answer: { question_id: qid, answer_array: ['an-option'] } }
assert_response :success assert_response :success
assert_match(/updated successfully/, JSON.parse(@response.body)['message']) assert_match(/updated successfully/, JSON.parse(@response.body)['message'])
@ -108,7 +108,7 @@ class QuizControllerTest < ActionDispatch::IntegrationTest
test 'should handle XHR fail' do test 'should handle XHR fail' do
setup_auth candidates(:peggy) setup_auth candidates(:peggy)
qid = questions(:fed10).id qid = questions(:fed10).id
post post_answer_path, xhr: true, params: { answer: { question_id: qid, checkbox: nil } } post post_answer_path, xhr: true, params: { answer: { question_id: qid, answer_array: [nil] } }
assert_response 400 assert_response 400
assert_match(/select.*answer/i, JSON.parse(@response.body).join) assert_match(/select.*answer/i, JSON.parse(@response.body).join)

View File

@ -22,6 +22,6 @@ class QuestionLiveCoderTest < ActionDispatch::IntegrationTest
get question_path(question.id) get question_path(question.id)
assert_response :success assert_response :success
assert_select '#answer_live_code_html', question.input_options['html'] assert_select '#answer_answer_hash_html', question.input_options['html']
end end
end end