diff --git a/.rubocop.yml b/.rubocop.yml index 7b9919e..47bed8a 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -25,6 +25,8 @@ Style/ExtraSpacing: Style/IndentationConsistency: EnforcedStyle: rails + Exclude: + - config/routes.rb Style/MethodDefParentheses: Enabled: false @@ -39,6 +41,7 @@ Style/StringLiterals: Metrics/AbcSize: Exclude: - db/migrate/**/* + Max: 27 Metrics/LineLength: Max: 110 @@ -51,3 +54,4 @@ Metrics/LineLength: Metrics/MethodLength: Exclude: - db/migrate/* + - app/controllers/* diff --git a/app/controllers/candidate_controller.rb b/app/controllers/candidate_controller.rb index f9d47b1..5cd5756 100644 --- a/app/controllers/candidate_controller.rb +++ b/app/controllers/candidate_controller.rb @@ -9,12 +9,25 @@ class CandidateController < ApplicationController redirect_to :summary and return if qid.nil? @question = current_candidate.fetch_question(qid) + @answer = Answer.new end - def update_question - redirect_to :summary and return if params.key?(:update) - redirect_to :saved and return if params.key?(:save) - redirect_to :question + def update_answer + answer_ids = { question_id: answer_params[:question_id], candidate_id: current_candidate.to_i } + @answer = Answer.find_or_create_by!(answer_ids) + @answer.answer = answer_for_type + @answer.saved = answer_params[:save] + @answer.submitted = answer_params[:next] + + if @answer.save + redirect_to :summary and return if params.key?(:update) + redirect_to :saved and return if params.key?(:save) + redirect_to :question + else + flash[:error] = [answer_params[:question_id]] + @question = current_candidate.fetch_question(qid) + render :question + end end def summary @@ -56,7 +69,18 @@ class CandidateController < ApplicationController private - def question_params - params.permit(:save) + def answer_params + params.require(:answer).permit( + :question_id, :answer_id, + :save, :next, :summary, + :radio, :text, checkbox: [], live_coder: [] + ) + end + + def answer_for_type + return answer_params[:radio] unless answer_params[:radio].nil? + return answer_params[:text] unless answer_params[:text].nil? + return answer_params[:checkbox] unless answer_params[:checkbox].nil? + return answer_params[:live_coder] unless answer_params[:live_coder].nil? end end diff --git a/app/views/candidate/_checkbox.html.erb b/app/views/candidate/_checkbox.html.erb index 96d1e11..ca06c9b 100644 --- a/app/views/candidate/_checkbox.html.erb +++ b/app/views/candidate/_checkbox.html.erb @@ -1,17 +1,19 @@ <% - question.input_options.each do | option | - option_id = "#{option.parameterize}_#{question.to_i}" + question.input_options.each_with_index do | option, i | + option_id = "#{question.question_id}_#{i}" + + checkbox_html = {class: 'checkbox', + id: "answer_#{option_id}", + name: "answer[checkbox][]", + checked: Array(question.answer).include?(option) + } %>
- - > - + <%= form.check_box(:answer, checkbox_html, option, '') %> + <%= form.label(option_id, option) %>
<% end %> --- MOVE TO FLASH HASH -- -
Please select or enter an answer.
+<% if flash[:error].try(:include?, question.to_i) %> +
Please select an answer.
+<% end %> diff --git a/app/views/candidate/_radio.html.erb b/app/views/candidate/_radio.html.erb index d5e124e..38a8bbd 100644 --- a/app/views/candidate/_radio.html.erb +++ b/app/views/candidate/_radio.html.erb @@ -1,17 +1,14 @@ <% question.input_options.each do | option | option_id = "#{option.parameterize}_#{question.to_i}" + radio_html = {class: 'radio', id: option_id} %>
- - > - + <%= radio_button_tag('answer[radio]', option, (question.answer == option), radio_html) %> + <%= label_tag(option_id, option) %>
<% end %> --- MOVE TO FLASH HASH -- -
Please select or enter an answer. (The character limit for a textarea answer is 1000)
+<% if flash[:error].try(:include?, question.to_i) %> +
Please select an answer.
+<% end %> diff --git a/app/views/candidate/_text.html.erb b/app/views/candidate/_text.html.erb index bf1a8f0..db29ee0 100644 --- a/app/views/candidate/_text.html.erb +++ b/app/views/candidate/_text.html.erb @@ -1,7 +1,8 @@ - - + +
Characters remaining:
--- MOVE TO FLASH HASH -- -
Please select or enter an answer. (The character limit for a textarea answer is 1000)
+<% if flash[:error].try(:include?, question.to_i) %> +
Please select or enter an answer. (The character limit for a textarea answer is 1000)
+<% end %> diff --git a/app/views/candidate/live_coder.html.erb b/app/views/candidate/live_coder.html.erb index c971f6b..331e3e0 100644 --- a/app/views/candidate/live_coder.html.erb +++ b/app/views/candidate/live_coder.html.erb @@ -13,7 +13,8 @@ --- MOVE TO FLASH HASH -- -
You must write code in one of the above textareas to progress.
+<% if flash[:error].try(:include?, @question.to_i) %> +
You must write code in one of the above textareas to progress.
+<% end %>
diff --git a/app/views/candidate/question.html.erb b/app/views/candidate/question.html.erb index 595259e..34eafc1 100644 --- a/app/views/candidate/question.html.erb +++ b/app/views/candidate/question.html.erb @@ -5,12 +5,14 @@ content_for :footer_title, "Skills Assessment" %> -<%= form_tag post_question_path, id: 'answer-form', data: {qid: @question.question_id} do %> +<%= form_for(@answer, url: post_answer_path(@answer.id), html:{id: 'answer-form', data: {qid: @question.question_id}}) do |form| %>

<%= @question.question %>

- <%= render partial: @question.input_type, locals: {question: @question} %> + <%= hidden_field_tag 'answer[question_id]', @question.question_id %> + <%= hidden_field_tag 'answer[answer_id]', @question.answer_id %> + <%= render partial: @question.input_type, locals: {question: @question, form: form} %>
<% if @status.on_summary %> diff --git a/app/views/candidate/summary.html.erb b/app/views/candidate/summary.html.erb index 4ab116c..5230789 100644 --- a/app/views/candidate/summary.html.erb +++ b/app/views/candidate/summary.html.erb @@ -5,8 +5,8 @@ Once you're done, hit the button at the bottom of the page to submit your answers.

- <%= form_tag(post_summary_path) do %> - <% @quiz.each do |question| %> + <% @quiz.each do |question| %> + <%= form_for(:answer, url: post_summary_path, html:{id: 'summary-form'}) do |form| %>
@@ -21,20 +21,21 @@
- <%= render partial: question.input_type, locals: {question: question} %> + <%= hidden_field_tag 'answer[question_id]', question.question_id %> + <%= render partial: question.input_type, locals: {question: question, form: form} %>
<% end #questions loop %> - - <% if @status.can_submit %> -
- -
- <% else %> -
Sorry, you must answer all questions before you can submit.
- <% end %> - <% end #form_tag %> + <% if @status.can_submit %> +
+ +
+ <% else %> +
Sorry, you must answer all questions before you can submit.
+ <% end %> + +
diff --git a/config/routes.rb b/config/routes.rb index b503f26..d52d09c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,16 +1,17 @@ Rails.application.routes.draw do - get "/welcome", to: "candidate#welcome", as: :welcome - get "/thankyou", to: "candidate#thankyou", as: :thankyou - get "/saved", to: "candidate#saved", as: :saved - get "/summary", to: "candidate#summary", as: :summary - post "/summary", to: "candidate#update_summary", as: :post_summary - post "/question", to: "candidate#update_question", as: :post_question - get "/question", to: "candidate#question", as: :question - post "/validate", to: "candidate#validate", as: :validate_candidate + post "/validate", to: "candidate#validate", as: :validate_candidate + get "/welcome", to: "candidate#welcome", as: :welcome + get "/thankyou", to: "candidate#thankyou", as: :thankyou + get "/saved", to: "candidate#saved", as: :saved - # live coder partial - get "/live-coder-entry/:question_id", to: "candidate#live_coder" + post "/question(/:answer_id)", to: "candidate#update_answer", as: :post_answer + get "/question(/:question_id)", to: "candidate#question", as: :question + get "/live-coder-entry/:question_id", to: "candidate#live_coder", as: :live_coder + + post "/summary", to: "candidate#update_summary", as: :post_summary + get "/summary", to: "candidate#summary", as: :summary root to: "candidate#welcome" + # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end diff --git a/db/sql/candidate_quiz.sql b/db/sql/candidate_quiz.sql new file mode 100644 index 0000000..0254f2d --- /dev/null +++ b/db/sql/candidate_quiz.sql @@ -0,0 +1,9 @@ +select c.id candidate_id + , c.name, c.test_hash + , q.quiz_id, q.id question_id, a.id answer_id, q.sort + , q.question, q.category, q.input_type, q.input_options, a.answer + , ifnull(a.saved, false) saved, ifnull(a.submitted, false) submitted , a.updated_at +from candidates c + inner join questions q on q.quiz_id = c.quiz_id + left join answers a on a.candidate_id = c.id AND a.question_id = q.id +order by c.name, q.sort; diff --git a/test/fixtures/answers.yml b/test/fixtures/answers.yml index f617658..ef29517 100644 --- a/test/fixtures/answers.yml +++ b/test/fixtures/answers.yml @@ -75,7 +75,7 @@ dawn6: dawn7: candidate: dawn question: fed7 - answer: {html: '

This means jQuery needs to be available in live-coder!

', css: "strong {font-size: 1.6em;}\n .green {color: green;}", js: '$("strong").addClass("green");'} + answer: {html: '

This means jQuery needs to be available in live-coder!

', css: "strong {font-size: 1.6em;}\n.green {color: green;}", js: '$("strong").addClass("green");'} saved: 0 submitted: true created_at: <%= DateTime.now() - 38.hours - 34.minutes %> @@ -165,7 +165,7 @@ richard6: richard7: candidate: richard question: fed7 - answer: {html: '

This means jQuery needs to be available in live-coder!

', css: "strong {font-size: 1.6em;} .green {color: green;}", js: '$("strong").addClass("green");'} + answer: {html: '

This means jQuery needs to be available in live-coder!

', css: "strong {font-size: 1.6em;}\n.green {color: green;}", js: '$("strong").addClass("green");'} saved: 0 submitted: true created_at: <%= DateTime.now() - 36.hours - 34.minutes %>