| @ -0,0 +1,33 @@ | |||||
| class AnswersController < ApplicationController | |||||
| include QuizHelperMethods | |||||
| # POST /q/:id/answer | |||||
| def create | |||||
| not_found unless question | |||||
| @answer = Answer.new(answer_params.merge(player_id: current_player.id, node_id: question.id)) | |||||
| respond_to do |format| | |||||
| if @answer.save | |||||
| format.html { redirect_to url_for(controller: 'questions', action: 'answer', id: params[:id]) } | |||||
| else | |||||
| format.html { render 'questions/show', status: :unprocessable_entity } | |||||
| end | |||||
| end | |||||
| end | |||||
| private | |||||
| # Only allow a list of trusted parameters through. | |||||
| def answer_params | |||||
| params.require(:answer).permit( | |||||
| :value | |||||
| ) | |||||
| end | |||||
| end | |||||
| @ -0,0 +1,60 @@ | |||||
| module QuizHelperMethods | |||||
| extend ActiveSupport::Concern | |||||
| included do | |||||
| before_action :require_player! | |||||
| before_action :set_locale | |||||
| helper_method :current_player, | |||||
| :questions, | |||||
| :question, | |||||
| :questions_size, | |||||
| :question_index | |||||
| end | |||||
| private | |||||
| def questions | |||||
| @questions ||= Node.at_depth(1).viewable.ordered.to_a | |||||
| end | |||||
| def question | |||||
| @question ||= questions[params[:id].to_i-1] | |||||
| end | |||||
| def questions_size | |||||
| @questions_size ||= questions.size + 1 | |||||
| end | |||||
| def question_index | |||||
| @question_index ||= (params[:id].to_i + 1) | |||||
| end | |||||
| def require_player! | |||||
| unless player_present? | |||||
| redirect_to url_for(controller: 'players', action: 'new') | |||||
| end | |||||
| end | |||||
| def current_player | |||||
| Current.player ||= player_from_session | |||||
| end | |||||
| def player_from_session | |||||
| Player.find_by(id: session[:player_id]) | |||||
| end | |||||
| def player_present? | |||||
| current_player.present? | |||||
| end | |||||
| end | |||||
| @ -0,0 +1,42 @@ | |||||
| class PlayersController < ApplicationController | |||||
| include QuizHelperMethods | |||||
| skip_before_action :require_player! | |||||
| # GET /player | |||||
| def new | |||||
| reset_session | |||||
| Current.player = nil | |||||
| @player = Player.new | |||||
| end | |||||
| # POST /player | |||||
| def create | |||||
| @player = Player.new(player_params.merge(locale: I18n.locale)) | |||||
| respond_to do |format| | |||||
| if @player.save | |||||
| session[:player_id] = @player.id | |||||
| format.html { redirect_to url_for(controller: 'questions', action: 'show', id: 1) } | |||||
| else | |||||
| format.html { render :new, status: :unprocessable_entity } | |||||
| end | |||||
| end | |||||
| end | |||||
| private | |||||
| # Only allow a list of trusted parameters through. | |||||
| def player_params | |||||
| params.require(:player).permit( | |||||
| :name | |||||
| ) | |||||
| end | |||||
| end | |||||
| @ -0,0 +1,24 @@ | |||||
| class QuestionsController < ApplicationController | |||||
| include QuizHelperMethods | |||||
| def show | |||||
| not_found unless question | |||||
| @answer = Answer.new(player_id: current_player.id, node_id: question.id) | |||||
| end | |||||
| def answer | |||||
| @answer = Answer.find_by(node_id: question.id, player_id: current_player.id) | |||||
| @question_answer = question.attachments.with_text.each_slice(2).to_a[@answer.value] | |||||
| end | |||||
| end | |||||
| @ -0,0 +1,2 @@ | |||||
| module AnswersHelper | |||||
| end | |||||
| @ -0,0 +1,2 @@ | |||||
| module PlayersHelper | |||||
| end | |||||
| @ -0,0 +1,2 @@ | |||||
| module QuestionsHelper | |||||
| end | |||||
| @ -0,0 +1,9 @@ | |||||
| class Answer < ApplicationRecord | |||||
| belongs_to :player | |||||
| belongs_to :node | |||||
| validates :value, presence: true | |||||
| validates :value, numericality: { only_integer: true, greater_than_or_equal_to: 0, less_than_or_equal_to: 1 } | |||||
| end | |||||
| @ -1,3 +1,3 @@ | |||||
| class Current < ActiveSupport::CurrentAttributes | class Current < ActiveSupport::CurrentAttributes | ||||
| attribute :user | |||||
| attribute :user, :player | |||||
| end | end | ||||
| @ -0,0 +1,7 @@ | |||||
| class Player < ApplicationRecord | |||||
| validates_presence_of :name | |||||
| has_many :answers, dependent: :destroy | |||||
| end | |||||
| @ -1,9 +1,10 @@ | |||||
| <turbo-stream action="append" targets="#attachments"> | <turbo-stream action="append" targets="#attachments"> | ||||
| <template> | <template> | ||||
| <% time_stamp = (Time.now.to_f * 1000).to_i %> | |||||
| <% @attachments.each_with_index do |attachment, i| %> | <% @attachments.each_with_index do |attachment, i| %> | ||||
| <% tmp_id = Time.now.to_i + i %> | |||||
| <% tmp_id = time_stamp + i %> | |||||
| <%= fields_for "#{@attachable_for.class.name.underscore.singularize}[attachments_attributes][#{ tmp_id }]", attachment do |builder| %> | <%= fields_for "#{@attachable_for.class.name.underscore.singularize}[attachments_attributes][#{ tmp_id }]", attachment do |builder| %> | ||||
| <%= render partial: 'admin/attachments/attachment', locals: {f: builder, tmp_id: tmp_id}, formats: :html %> | |||||
| <%= render partial: 'admin/attachments/attachment', locals: {f: builder, tmp_id: tmp_id}, formats: :html %> | |||||
| <% end %> | <% end %> | ||||
| <% end %> | <% end %> | ||||
| </template> | </template> | ||||
| @ -1,6 +1,7 @@ | |||||
| <% Node.roots.first.attachments.limit(2).each_with_index do |attachment, i| %> | |||||
| <% Node.roots.viewable.first.attachments.limit(2).each_with_index do |attachment, i| %> | |||||
| <%= tag.div attachment.body.html_safe, class: i == 0 ? "intro-content-header" : "intro-content-body" %> | <%= tag.div attachment.body.html_safe, class: i == 0 ? "intro-content-header" : "intro-content-body" %> | ||||
| <% end %> | <% end %> | ||||
| <%= link_to t('get_started'), Node.roots.first.children.first.url, class: 'button__base' %> | |||||
| <%= link_to t('get_started'), url_for(controller: 'players', action: 'new', locale: I18n.locale), class: 'button__base' %> | |||||
| @ -0,0 +1,26 @@ | |||||
| <%- | |||||
| content_for :title, t('what_is_your_name') | |||||
| %> | |||||
| <%= form_with model: @player, url: url_for(controller: 'players', action: 'create') do |form| %> | |||||
| <div class="question-container"> | |||||
| <div class="question-step"> | |||||
| <div>1/<%= questions_size %></div> | |||||
| </div> | |||||
| <div class="question-header"> | |||||
| <%= t 'what_is_your_name' %> | |||||
| </div> | |||||
| <%= form.label :name, class: "question-answer" do %> | |||||
| <%= form.text_field :name, placeholder: t('what_is_your_name') %> | |||||
| <% end %> | |||||
| <%= form.submit t('submit'), class: 'button__base' %> | |||||
| </div> | |||||
| <% end %> | |||||
| @ -0,0 +1,19 @@ | |||||
| <%- | |||||
| content_for :title, question.page_title.blank? ? question.title : question.page_title | |||||
| content_for :meta_description, question.page_description | |||||
| %> | |||||
| <div class="question-container"> | |||||
| <div class="question-step"> | |||||
| <div><%= question_index %>/<%= questions_size %></div> | |||||
| </div> | |||||
| <div class="question-result"> | |||||
| <%= @question_answer.last.body.html_safe %> | |||||
| </div> | |||||
| <%= link_to t('next_question'), url_for(controller: 'questions', action: 'show', id: question_index), class: 'button__base' %> | |||||
| </div> | |||||
| @ -0,0 +1,31 @@ | |||||
| <%- | |||||
| content_for :title, question.page_title.blank? ? question.title : question.page_title | |||||
| content_for :meta_description, question.page_description | |||||
| %> | |||||
| <%= form_with model: @answer, url: url_for(controller: 'answers', action: 'create') do |form| %> | |||||
| <div class="question-container"> | |||||
| <div class="question-step"> | |||||
| <div><%= question_index %>/<%= questions_size %></div> | |||||
| </div> | |||||
| <div class="question-header"> | |||||
| <%= question.title %> | |||||
| </div> | |||||
| <% question.attachments.with_text.each_slice(2).each_with_index do |answer_option, i| %> | |||||
| <div class="question-answer"> | |||||
| <%= form.label :value, for: nil do %> | |||||
| <%= answer_option.first.body.html_safe %> | |||||
| <%= form.radio_button :value, i %> | |||||
| <%- end -%> | |||||
| </div> | |||||
| <% end %> | |||||
| <%= form.submit t('submit'), class: 'button__base' %> | |||||
| </div> | |||||
| <% end %> | |||||
| @ -0,0 +1,11 @@ | |||||
| class CreatePlayers < ActiveRecord::Migration[8.0] | |||||
| def change | |||||
| create_table :players do |t| | |||||
| t.text :name | |||||
| t.text :locale | |||||
| t.timestamps | |||||
| end | |||||
| end | |||||
| end | |||||
| @ -0,0 +1,14 @@ | |||||
| class CreateAnswers < ActiveRecord::Migration[8.0] | |||||
| def change | |||||
| create_table :answers do |t| | |||||
| t.references :player | |||||
| t.references :node | |||||
| t.integer :value, default: nil, index: true | |||||
| t.timestamps | |||||
| end | |||||
| end | |||||
| end | |||||
| @ -0,0 +1,7 @@ | |||||
| require "test_helper" | |||||
| class AnswersControllerTest < ActionDispatch::IntegrationTest | |||||
| # test "the truth" do | |||||
| # assert true | |||||
| # end | |||||
| end | |||||
| @ -0,0 +1,7 @@ | |||||
| require "test_helper" | |||||
| class PlayersControllerTest < ActionDispatch::IntegrationTest | |||||
| # test "the truth" do | |||||
| # assert true | |||||
| # end | |||||
| end | |||||
| @ -0,0 +1,7 @@ | |||||
| require "test_helper" | |||||
| class QuestionsControllerTest < ActionDispatch::IntegrationTest | |||||
| # test "the truth" do | |||||
| # assert true | |||||
| # end | |||||
| end | |||||
| @ -0,0 +1,11 @@ | |||||
| # Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html | |||||
| # This model initially had no columns defined. If you add columns to the | |||||
| # model remove the "{}" from the fixture names and add the columns immediately | |||||
| # below each fixture, per the syntax in the comments below | |||||
| # | |||||
| one: {} | |||||
| # column: value | |||||
| # | |||||
| two: {} | |||||
| # column: value | |||||
| @ -0,0 +1,11 @@ | |||||
| # Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html | |||||
| # This model initially had no columns defined. If you add columns to the | |||||
| # model remove the "{}" from the fixture names and add the columns immediately | |||||
| # below each fixture, per the syntax in the comments below | |||||
| # | |||||
| one: {} | |||||
| # column: value | |||||
| # | |||||
| two: {} | |||||
| # column: value | |||||
| @ -0,0 +1,7 @@ | |||||
| require "test_helper" | |||||
| class AnswerTest < ActiveSupport::TestCase | |||||
| # test "the truth" do | |||||
| # assert true | |||||
| # end | |||||
| end | |||||
| @ -0,0 +1,7 @@ | |||||
| require "test_helper" | |||||
| class PlayerTest < ActiveSupport::TestCase | |||||
| # test "the truth" do | |||||
| # assert true | |||||
| # end | |||||
| end | |||||