All basic question types

This commit is contained in:
Charlotte Van Petegem 2025-04-27 00:13:20 +02:00
parent 3e1e5618ca
commit 4fe218166f
Signed by: chvp
SSH key fingerprint: SHA256:s9rb8jBVfdahqWHuBAcHCBP1wmj4eYQXZfqgz4H3E9E
51 changed files with 760 additions and 92 deletions

58
.annotaterb.yml Normal file
View file

@ -0,0 +1,58 @@
---
:position: before
:position_in_additional_file_patterns: before
:position_in_class: before
:position_in_factory: before
:position_in_fixture: before
:position_in_routes: before
:position_in_serializer: before
:position_in_test: before
:classified_sort: true
:exclude_controllers: true
:exclude_factories: false
:exclude_fixtures: false
:exclude_helpers: true
:exclude_scaffolds: true
:exclude_serializers: false
:exclude_sti_subclasses: false
:exclude_tests: false
:force: false
:format_markdown: false
:format_rdoc: false
:format_yard: false
:frozen: false
:ignore_model_sub_dir: false
:ignore_unknown_models: false
:include_version: false
:show_check_constraints: false
:show_complete_foreign_keys: false
:show_foreign_keys: true
:show_indexes: true
:simple_indexes: false
:sort: false
:timestamp: false
:trace: false
:with_comment: true
:with_column_comments: true
:with_table_comments: true
:active_admin: false
:command:
:debug: false
:hide_default_column_types: ''
:hide_limit_column_types: ''
:ignore_columns:
:ignore_routes:
:models: true
:routes: false
:skip_on_db_migrate: false
:target_action: :do_annotations
:wrapper:
:wrapper_close:
:wrapper_open:
:classes_default_to_s: []
:additional_file_patterns: []
:model_dir:
- app/models
:require: []
:root_dir:
- ''

View file

@ -40,6 +40,7 @@ group :development, :test do
end
group :development do
gem "annotaterb", require: false
# Use console on exceptions pages [https://github.com/rails/web-console]
gem "web-console"
end

View file

@ -74,6 +74,7 @@ GEM
uri (>= 0.13.1)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
annotaterb (4.14.0)
base64 (0.2.0)
benchmark (0.4.0)
bigdecimal (3.1.9)
@ -282,6 +283,7 @@ PLATFORMS
x86_64-linux-musl
DEPENDENCIES
annotaterb
bootsnap
brakeman
capybara

View file

@ -1,4 +1,16 @@
class ApplicationController < ActionController::Base
# Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has.
allow_browser versions: :modern
before_action :require_authorization
def authorized?
cookies.signed[:_entrance_exam_authorized].present?
end
private
def require_authorization
redirect_to new_sessions_path unless authorized?
end
end

View file

@ -0,0 +1,23 @@
class QuestionsController < ApplicationController
def answer
question = Question.find(params[:id])
@answer = Answer.find_or_initialize_by(question:)
send(:"handle_#{question.answer_kind}_answer")
end
private
def handle_simple_answer
@answer.update!(data: params[:value])
end
def handle_image_answer
@answer.image.attach(
io: StringIO.new(Base64.decode64(params[:data])),
filename: params[:filename],
content_type: params[:mimetype],
)
@answer.save!
end
end

View file

@ -0,0 +1,10 @@
class SectionsController < ApplicationController
def index
@sections = Section.all
end
def show
@section = Section.find(params[:id])
@questions = @section.questions.includes(:answer)
end
end

View file

@ -0,0 +1,25 @@
class SessionsController < ApplicationController
skip_before_action :require_authorization
def new
redirect_to sections_path if authorized?
end
def create
if authorized?
redirect_to sections_path
return
end
if Rails.configuration.entrance_exam_token != params[:token]
redirect_to new_sessions_path
return
end
cookies.signed[:_entrance_exam_authorized] = {
value: true,
expires: 1.year
}
redirect_to sections_path
end
end

View file

@ -0,0 +1,2 @@
module QuestionsHelper
end

View file

@ -0,0 +1,2 @@
module SectionsHelper
end

View file

@ -0,0 +1,2 @@
module SessionsHelper
end

View file

@ -1 +1,8 @@
// Entry point for the build script in your package.json
import initSimpleQuestions from './simple_input.js'
import initImageQuestions from './image_input.js'
addEventListener("DOMContentLoaded", () => {
initSimpleQuestions()
initImageQuestions()
})

View file

@ -0,0 +1,35 @@
const csrfToken = document.querySelector("[name='csrf-token']").content
export default function initImageQuestions() {
document.querySelectorAll('[data-behaviour="question_image_input"]').forEach((input) => {
const submitUrl = input.dataset.submitUrl
input.addEventListener('change', () => {
const file = input.files[0];
const fileReader = new FileReader();
fileReader.onload = (ev) => {
fetch(submitUrl, {
method: 'PUT',
headers: {
"x-csrf-token": csrfToken,
"content-type": "application/json",
},
body: JSON.stringify({
filename: file.name,
mimetype: file.type,
data: ev.target.result.replace(/^data:[a-zA-Z0-9!#$%^&\\*_\-+{}|'.`~]+\/[a-zA-Z0-9!#$%^&\\*_\-+{}|'.`~]+;base64,/, ""),
})
})
}
fileReader.readAsDataURL(file);
const preview = document.querySelector(`#${input.id}_preview`)
while (preview.firstChild) {
preview.removeChild(preview.firstChild)
}
const previewImage = document.createElement("img")
previewImage.src = URL.createObjectURL(file)
previewImage.alt = previewImage.title = file.name
preview.appendChild(previewImage)
})
})
}

View file

@ -0,0 +1,23 @@
import debounce from 'debounce'
const csrfToken = document.querySelector("[name='csrf-token']").content
export default function initSimpleQuestions() {
document.querySelectorAll('[data-behaviour="question_simple_input"]').forEach((input) => {
const submitUrl = input.dataset.submitUrl
const handleInput = debounce(() => {
fetch(submitUrl, {
method: 'PUT',
headers: {
"x-csrf-token": csrfToken,
"content-type": "application/json",
},
body: JSON.stringify({ value: input.value }),
})
}, 300)
input.addEventListener('change', handleInput)
input.addEventListener('input', handleInput)
})
}

View file

@ -1,3 +1,25 @@
# == Schema Information
#
# Table name: answers
#
# id :integer not null, primary key
# data :text
# created_at :datetime not null
# updated_at :datetime not null
# question_id :integer not null
#
# Indexes
#
# index_answers_on_question_id (question_id)
#
# Foreign Keys
#
# question_id (question_id => questions.id)
#
class Answer < ApplicationRecord
belongs_to :question
has_one_attached :image
serialize :data, coder: JSON
end

View file

@ -1,3 +1,28 @@
# == Schema Information
#
# Table name: questions
#
# id :integer not null, primary key
# answer_kind :integer not null
# public_asset_path :string
# question_kind :integer default("simple"), not null
# text :text not null
# created_at :datetime not null
# updated_at :datetime not null
# section_id :integer not null
#
# Indexes
#
# index_questions_on_section_id (section_id)
#
# Foreign Keys
#
# section_id (section_id => sections.id)
#
class Question < ApplicationRecord
enum :answer_kind, { simple: 0, image: 1, politicians: 2 }, prefix: true
enum :question_kind, { simple: 0, video: 1 }, prefix: true
belongs_to :section
has_one :answer
end

View file

@ -1,2 +1,13 @@
# == Schema Information
#
# Table name: sections
#
# id :integer not null, primary key
# description :text not null
# title :text not null
# created_at :datetime not null
# updated_at :datetime not null
#
class Section < ApplicationRecord
has_many :questions
end

View file

@ -3,23 +3,18 @@
<head>
<title><%= content_for(:title) || "Entrance Exam" %></title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= yield :head %>
<%# Enable PWA manifest for installable apps (make sure to enable in config/routes.rb too!) %>
<%#= tag.link rel: "manifest", href: pwa_manifest_path(format: :json) %>
<link rel="icon" href="/icon.png" type="image/png">
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/icon.png">
<%# Includes all stylesheet files in app/assets/stylesheets %>
<%= stylesheet_link_tag :app %>
<%= javascript_include_tag "application", "data-turbo-track": "reload", type: "module" %>
<%= javascript_include_tag "application" %>
</head>
<body>

View file

@ -1,22 +0,0 @@
{
"name": "EntranceExam",
"icons": [
{
"src": "/icon.png",
"type": "image/png",
"sizes": "512x512"
},
{
"src": "/icon.png",
"type": "image/png",
"sizes": "512x512",
"purpose": "maskable"
}
],
"start_url": "/",
"display": "standalone",
"scope": "/",
"description": "EntranceExam.",
"theme_color": "red",
"background_color": "red"
}

View file

@ -1,26 +0,0 @@
// Add a service worker for processing Web Push notifications:
//
// self.addEventListener("push", async (event) => {
// const { title, options } = await event.data.json()
// event.waitUntil(self.registration.showNotification(title, options))
// })
//
// self.addEventListener("notificationclick", function(event) {
// event.notification.close()
// event.waitUntil(
// clients.matchAll({ type: "window" }).then((clientList) => {
// for (let i = 0; i < clientList.length; i++) {
// let client = clientList[i]
// let clientPath = (new URL(client.url)).pathname
//
// if (clientPath == event.notification.data.path && "focus" in client) {
// return client.focus()
// }
// }
//
// if (clients.openWindow) {
// return clients.openWindow(event.notification.data.path)
// }
// })
// )
// })

View file

@ -0,0 +1,12 @@
<div id="<%= "question_answer_#{question.id}_preview" %>">
<% if question.answer.present? %>
<%= image_tag question.answer.image %>
<% end %>
</div>
<input id="<%= "question_answer_#{question.id}" %>"
type="file"
accept=".jpg,.jpeg,.png,.webp,image/jpg,image/jpeg,image/png,image/webp"
autocomplete="off"
data-behaviour="question_image_input"
data-submit-url="<%= answer_question_url(question.id) %>"
/>

View file

@ -0,0 +1,3 @@
<div>
This one's going to be hard...
</div>

View file

@ -0,0 +1,7 @@
<input id="<%= "question_answer_#{question.id}" %>"
type="text"
value="<%= question.answer&.data || '' %>"
autocomplete="off"
data-behaviour="question_simple_input"
data-submit-url="<%= answer_question_url(question.id) %>"
/>

View file

@ -0,0 +1 @@
<%= question.text %>

View file

@ -0,0 +1 @@
<video src="<%= question.public_asset_path %>" controls preload="metadata"></video>

View file

@ -0,0 +1,5 @@
<% @sections.each do |section| %>
<p>
<%= link_to section.title, section_url(section) %>
</p>
<% end %>

View file

@ -0,0 +1,10 @@
<h4><%= @section.title %></h4>
<p><%= @section.description %></p>
<% @questions.each do |question| %>
<section>
<%= render partial: "questions/#{question.question_kind}_show", locals: { question: } %>
<%= render partial: "questions/#{question.answer_kind}_form", locals: { question: } %>
</section>
<% end %>

View file

@ -0,0 +1,5 @@
<%= form_with url: sessions_path, method: :post do |form| %>
<%= form.label :token, "Token" %>
<%= form.password_field :token %>
<%= form.submit "Start exam" %>
<% end %>

View file

@ -35,5 +35,6 @@ module EntranceExam
#
# config.time_zone = "Central Time (US & Canada)"
# config.eager_load_paths << Rails.root.join("extras")
config.entrance_exam_token = "password"
end
end

View file

@ -10,5 +10,15 @@ Rails.application.routes.draw do
# get "service-worker" => "rails/pwa#service_worker", as: :pwa_service_worker
# Defines the root path route ("/")
# root "posts#index"
root "sessions#new"
resources "sessions", only: [:new, :create]
resources "sections", only: [:index, :show]
resources "questions", only: [] do
member do
put :answer
end
end
end

View file

@ -0,0 +1,57 @@
# This migration comes from active_storage (originally 20170806125915)
class CreateActiveStorageTables < ActiveRecord::Migration[7.0]
def change
# Use Active Record's configured type for primary and foreign keys
primary_key_type, foreign_key_type = primary_and_foreign_key_types
create_table :active_storage_blobs, id: primary_key_type do |t|
t.string :key, null: false
t.string :filename, null: false
t.string :content_type
t.text :metadata
t.string :service_name, null: false
t.bigint :byte_size, null: false
t.string :checksum
if connection.supports_datetime_with_precision?
t.datetime :created_at, precision: 6, null: false
else
t.datetime :created_at, null: false
end
t.index [ :key ], unique: true
end
create_table :active_storage_attachments, id: primary_key_type do |t|
t.string :name, null: false
t.references :record, null: false, polymorphic: true, index: false, type: foreign_key_type
t.references :blob, null: false, type: foreign_key_type
if connection.supports_datetime_with_precision?
t.datetime :created_at, precision: 6, null: false
else
t.datetime :created_at, null: false
end
t.index [ :record_type, :record_id, :name, :blob_id ], name: :index_active_storage_attachments_uniqueness, unique: true
t.foreign_key :active_storage_blobs, column: :blob_id
end
create_table :active_storage_variant_records, id: primary_key_type do |t|
t.belongs_to :blob, null: false, index: false, type: foreign_key_type
t.string :variation_digest, null: false
t.index [ :blob_id, :variation_digest ], name: :index_active_storage_variant_records_uniqueness, unique: true
t.foreign_key :active_storage_blobs, column: :blob_id
end
end
private
def primary_and_foreign_key_types
config = Rails.configuration.generators
setting = config.options[config.orm][:primary_key_type]
primary_key_type = setting || :primary_key
foreign_key_type = setting || :bigint
[ primary_key_type, foreign_key_type ]
end
end

View file

@ -0,0 +1,5 @@
class AnswerDataNullable < ActiveRecord::Migration[8.0]
def change
change_column_null :answers, :data, true
end
end

View file

@ -0,0 +1,5 @@
class QuestionRenameTypeKind < ActiveRecord::Migration[8.0]
def change
rename_column :questions, :type, :kind
end
end

View file

@ -0,0 +1,6 @@
class QuestionQuestionKind < ActiveRecord::Migration[8.0]
def change
rename_column :questions, :kind, :answer_kind
add_column :questions, :question_kind, :integer, null: false, default: 0
end
end

View file

@ -0,0 +1,5 @@
class QuestionAssetName < ActiveRecord::Migration[8.0]
def change
add_column :questions, :asset_name, :string, null: true
end
end

View file

@ -0,0 +1,5 @@
class QuestionRenameAssetNamePublicAssetPath < ActiveRecord::Migration[8.0]
def change
rename_column :questions, :asset_name, :public_asset_path
end
end

72
db/schema.rb generated Normal file
View file

@ -0,0 +1,72 @@
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# This file is the source Rails uses to define your schema when running `bin/rails
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
# be faster and is potentially less error prone than running all of your
# migrations from scratch. Old migrations may fail to apply correctly if those
# migrations use external dependencies or application code.
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[8.0].define(version: 2025_04_26_202909) do
create_table "active_storage_attachments", force: :cascade do |t|
t.string "name", null: false
t.string "record_type", null: false
t.bigint "record_id", null: false
t.bigint "blob_id", null: false
t.datetime "created_at", null: false
t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
end
create_table "active_storage_blobs", force: :cascade do |t|
t.string "key", null: false
t.string "filename", null: false
t.string "content_type"
t.text "metadata"
t.string "service_name", null: false
t.bigint "byte_size", null: false
t.string "checksum"
t.datetime "created_at", null: false
t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
end
create_table "active_storage_variant_records", force: :cascade do |t|
t.bigint "blob_id", null: false
t.string "variation_digest", null: false
t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true
end
create_table "answers", force: :cascade do |t|
t.integer "question_id", null: false
t.text "data"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["question_id"], name: "index_answers_on_question_id"
end
create_table "questions", force: :cascade do |t|
t.integer "section_id", null: false
t.text "text", null: false
t.integer "answer_kind", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "question_kind", default: 0, null: false
t.string "public_asset_path"
t.index ["section_id"], name: "index_questions_on_section_id"
end
create_table "sections", force: :cascade do |t|
t.text "title", null: false
t.text "description", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
add_foreign_key "answers", "questions"
add_foreign_key "questions", "sections"
end

View file

@ -7,3 +7,5 @@
# ["Action", "Comedy", "Drama", "Horror"].each do |genre_name|
# MovieGenre.find_or_create_by!(name: genre_name)
# end
Rake.application["db:fixtures:load"].invoke

View file

@ -0,0 +1,8 @@
# This rake task was added by annotate_rb gem.
# Can set `ANNOTATERB_SKIP_ON_DB_TASKS` to be anything to skip this
if Rails.env.development? && ENV["ANNOTATERB_SKIP_ON_DB_TASKS"].nil?
require "annotate_rb"
AnnotateRb::Core.load_rake_tasks
end

View file

@ -1,18 +1,19 @@
{
"name": "app",
"private": true,
"devDependencies": {
"esbuild": "^0.25.3"
},
"scripts": {
"build": "esbuild app/javascript/*.* --bundle --sourcemap --format=esm --outdir=app/assets/builds --public-path=/assets",
"build:css": "postcss ./app/assets/stylesheets/application.postcss.css -o ./app/assets/builds/application.css"
},
"dependencies": {
"autoprefixer": "^10.4.21",
"postcss": "^8.5.3",
"postcss-cli": "^11.0.1",
"postcss-import": "^16.1.0",
"postcss-nesting": "^13.0.1"
}
"name": "app",
"private": true,
"scripts": {
"build:js": "esbuild app/javascript/*.* --bundle --sourcemap --format=esm --outdir=app/assets/builds --public-path=/assets",
"build:css": "postcss ./app/assets/stylesheets/application.postcss.css -o ./app/assets/builds/application.css"
},
"dependencies": {
"autoprefixer": "^10.4.21",
"debounce": "^2.2.0",
"postcss": "^8.5.3",
"postcss-cli": "^11.0.1",
"postcss-import": "^16.1.0",
"postcss-nesting": "^13.0.1"
},
"devDependencies": {
"esbuild": "^0.25.3"
}
}

Binary file not shown.

BIN
public/videos/stijn.mp4 Normal file

Binary file not shown.

View file

@ -0,0 +1,7 @@
require "test_helper"
class QuestionsControllerTest < ActionDispatch::IntegrationTest
# test "the truth" do
# assert true
# end
end

View file

@ -0,0 +1,7 @@
require "test_helper"
class SectionsControllerTest < ActionDispatch::IntegrationTest
# test "the truth" do
# assert true
# end
end

View file

@ -0,0 +1,7 @@
require "test_helper"
class SessionsControllerTest < ActionDispatch::IntegrationTest
# test "the truth" do
# assert true
# end
end

View file

@ -1,9 +1,20 @@
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
one:
question: one
data: MyText
two:
question: two
data: MyText
# == Schema Information
#
# Table name: answers
#
# id :integer not null, primary key
# data :text
# created_at :datetime not null
# updated_at :datetime not null
# question_id :integer not null
#
# Indexes
#
# index_answers_on_question_id (question_id)
#
# Foreign Keys
#
# question_id (question_id => questions.id)
#

View file

@ -1,11 +1,151 @@
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
one:
section: one
text: MyText
type: 1
# == Schema Information
#
# Table name: questions
#
# id :integer not null, primary key
# answer_kind :integer not null
# public_asset_path :string
# question_kind :integer default("simple"), not null
# text :text not null
# created_at :datetime not null
# updated_at :datetime not null
# section_id :integer not null
#
# Indexes
#
# index_questions_on_section_id (section_id)
#
# Foreign Keys
#
# section_id (section_id => sections.id)
#
sport_bashir:
section: sport
text: In welke straat groeide Bashir Abdi op?
answer_kind: <%= Question.answer_kinds[:simple] %>
question_kind: <%= Question.question_kinds[:simple] %>
two:
section: two
text: MyText
type: 1
sport_club:
section: sport
text: In welke sport versloeg een Gentse club ooit een team uit Oxford?
answer_kind: <%= Question.answer_kinds[:simple] %>
question_kind: <%= Question.question_kinds[:simple] %>
sport_sabbe:
section: sport
text: Waar ligt de Karel Sabbeberg?
answer_kind: <%= Question.answer_kinds[:simple] %>
question_kind: <%= Question.question_kinds[:simple] %>
sport_aagent:
section: sport
text: Wat is de meest recente beker van Belgie die AA Gent gewonnen heeft waar Tomas niet in het stadion zat?
answer_kind: <%= Question.answer_kinds[:simple] %>
question_kind: <%= Question.question_kinds[:simple] %>
sport_hockey:
section: sport
text: ""
answer_kind: <%= Question.answer_kinds[:simple] %>
question_kind: <%= Question.question_kinds[:video] %>
public_asset_path: "/videos/els_en_geert.mp4"
sport_busschaert:
section: sport
text: Neem een foto op het bankje van Matthias Busschaert (en wandel een rondje rond de Watersportbaan).
answer_kind: <%= Question.answer_kinds[:image] %>
question_kind: <%= Question.question_kinds[:simple] %>
sport_klimmen:
section: sport
text: Bemachtig een foto van Charlotte terwijl ze aan het klimmen is zonder dat ze het merkt.
answer_kind: <%= Question.answer_kinds[:image] %>
question_kind: <%= Question.question_kinds[:simple] %>
life_haven:
section: life
text: Wat moet je 24u voor het binnenkomen van de haven in Gent doen?
answer_kind: <%= Question.answer_kinds[:simple] %>
question_kind: <%= Question.question_kinds[:simple] %>
life_pendelaars:
section: life
text: Hoeveel pendelaars komen dagelijks van buiten Gent in Gent werken?
answer_kind: <%= Question.answer_kinds[:simple] %>
question_kind: <%= Question.question_kinds[:simple] %>
life_repetitieruimtes:
section: life
text: Hoeveel repetitieruimtes en ateliers waren er vroeger in de Leopoldskazerne?
answer_kind: <%= Question.answer_kinds[:simple] %>
question_kind: <%= Question.question_kinds[:simple] %>
life_stam:
section: life
text: Op welke tegel ligt de Leopoldskazerne in het STAM?
answer_kind: <%= Question.answer_kinds[:simple] %>
question_kind: <%= Question.question_kinds[:simple] %>
life_bollekesschool:
section: life
text: Wat is de bollekesschool?
answer_kind: <%= Question.answer_kinds[:simple] %>
question_kind: <%= Question.question_kinds[:simple] %>
life_langst:
section: life
text: Wie woont er al het langst in Gent?
answer_kind: <%= Question.answer_kinds[:simple] %>
question_kind: <%= Question.question_kinds[:simple] %>
life_haven_oprichting:
section: life
text: ""
answer_kind: <%= Question.answer_kinds[:simple] %>
question_kind: <%= Question.question_kinds[:video] %>
public_asset_path: "/videos/stijn.mp4"
politics_regenpijpen:
section: politics
text: Welke kleur hebben de regenpijpen van het stadhuis en waarom?
answer_kind: <%= Question.answer_kinds[:simple] %>
question_kind: <%= Question.question_kinds[:simple] %>
politics_schepenen:
section: politics
text: Verbind de schepenen en hun bevoegdheden.
answer_kind: <%= Question.answer_kinds[:politicians] %>
question_kind: <%= Question.question_kinds[:simple] %>
politics_anneleen:
section: politics
text: Hoeveel keer is Anneleen al op haar gezicht gegaan (fysiek en metaforisch)?
answer_kind: <%= Question.answer_kinds[:simple] %>
question_kind: <%= Question.question_kinds[:simple] %>
politics_langste:
section: politics
text: Wie was de langste burgemeester van Gent?
answer_kind: <%= Question.answer_kinds[:simple] %>
question_kind: <%= Question.question_kinds[:simple] %>
politics_langst:
section: politics
text: Wie was er het langst burgemeester van Gent?
answer_kind: <%= Question.answer_kinds[:simple] %>
question_kind: <%= Question.question_kinds[:simple] %>
politics_nazi:
section: politics
text: Welke Gentse burgemeester is niet opgenomen in de officiële lijst van Gentse burgemeesters?
answer_kind: <%= Question.answer_kinds[:simple] %>
question_kind: <%= Question.question_kinds[:simple] %>
politics_jorg:
section: politics
text: Hoeveel stemmen kwam Jorg te kort om in de provincieraad te zetelen?
answer_kind: <%= Question.answer_kinds[:simple] %>
question_kind: <%= Question.question_kinds[:simple] %>

View file

@ -1,9 +1,23 @@
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
one:
title: MyText
description: MyText
# == Schema Information
#
# Table name: sections
#
# id :integer not null, primary key
# description :text not null
# title :text not null
# created_at :datetime not null
# updated_at :datetime not null
#
sport:
title: Sport
description: Gent is een sportieve stad, dus daarom enkele vragen daarover.
two:
title: MyText
description: MyText
life:
title: Leven, werken en wonen
description: In Gent moet er ook geleefd worden.
politics:
title: Politiek
description: De Gentse politiek is interessanter dan de Duffelse!

View file

@ -1,3 +1,21 @@
# == Schema Information
#
# Table name: answers
#
# id :integer not null, primary key
# data :text
# created_at :datetime not null
# updated_at :datetime not null
# question_id :integer not null
#
# Indexes
#
# index_answers_on_question_id (question_id)
#
# Foreign Keys
#
# question_id (question_id => questions.id)
#
require "test_helper"
class AnswerTest < ActiveSupport::TestCase

View file

@ -1,3 +1,24 @@
# == Schema Information
#
# Table name: questions
#
# id :integer not null, primary key
# answer_kind :integer not null
# public_asset_path :string
# question_kind :integer default("simple"), not null
# text :text not null
# created_at :datetime not null
# updated_at :datetime not null
# section_id :integer not null
#
# Indexes
#
# index_questions_on_section_id (section_id)
#
# Foreign Keys
#
# section_id (section_id => sections.id)
#
require "test_helper"
class QuestionTest < ActiveSupport::TestCase

View file

@ -1,3 +1,13 @@
# == Schema Information
#
# Table name: sections
#
# id :integer not null, primary key
# description :text not null
# title :text not null
# created_at :datetime not null
# updated_at :datetime not null
#
require "test_helper"
class SectionTest < ActiveSupport::TestCase

View file

@ -237,6 +237,11 @@ cssesc@^3.0.0:
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
debounce@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/debounce/-/debounce-2.2.0.tgz#f895fa2fbdb579a0f0d3dcf5dde19657e50eaad5"
integrity sha512-Xks6RUDLZFdz8LIdR6q0MTH44k7FikOmnh5xkSjMig6ch45afc8sjTjRQf3P6ax8dMgcQrYO/AR2RGWURrruqw==
dependency-graph@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-1.0.0.tgz#bb5e85aec1310bc13b22dbd76e3196c4ee4c10d2"