Для изучения ruby был выбран учебный проект в котором простая задача, написания тестов для web. Ввиду отсутствия знаний и опыта было решено использовать упрощенный фреймворк sinatra. В результате, в моем решении этой задачи всего два файла. Первый это mutaAlim.json, в котором у нас база данных в json формате.
Рассмотрим структуру этого файла на примере нескольких вопросов:
[
{
"id" : 1,
"question" : "Ассаламу Алейкум!",
"answers" : ["Ваалейкум Ассалам", "Привет", "Здорово", "Хай"]
},
{
"id" : 2,
"question" : "Как дела?",
"answers" : ["альхамдуЛилягь", "Плохо", "хорошо", "шикарно"]
}, …..(другие вопросы в таком же порядке)
]
У нас таким образом в json массив из хеш элементов.
Ответы в массиве по ключу answers, в котором первый вариант ответа является правильным.
Второй файл mutaAlim.rb в котором код приложения.
Рассмотрим его поближе. Первые строчки подключают гемы sinatra и json:
require 'sinatra'
require 'json'
Для перехода на страницу приветствия следующий код
get '/' do
erb :index
end
При переходе по адресу у нас откроется страничка, которая описана в том же файле:
@@index
<!DOCTYPE html>
<html>
<head>
<title>Главная</title>
</head>
<body>
<h1> Ассаламу гIалайкум ва раhматуЛлаhи ва баракатуhу!</h1>
<h1> Мира вам, Милости и Благославления Всевышнего!</h1>
<h1> Сайт для тестирования базовых знаний</h1>
<h2>Описание </h2>
<div>
<p> Этот сайт предназначен для тех кто хочет проверить свои знания. </p>
</div>
<input value="Начать тест" name="test_begin" onclick="location.href='/test'" type="button">
</body>
</html>
Простая страничка с кнопкой для перехода на страничку тестов. Далее в коде у нас переменные необходимые для работы приложения:
#хеш с тестами
@@test_hash
#количество тестов
@@kol_testov = 13
#массив из случайно выбранных неповторяющихся вопросов
@@mas_test_number = Array.new(@@kol_testov)
#массив с ответами, -1 если не ответили на вопрос иначе номер ответа
@@mas_test_answer
#считываем файл с тестами
test_file = File.open('mutaAlim.json',"rb")
@@test_hash = JSON.parse(test_file.read)
test_file.close
#для таблицы результатов
@@not_answer = "Вы не дали ответ"
#количество ответов
@@answers
#количество правильных ответов
@@ball
#процент правильных ответов
@@procent_tru_answers
#массив в котором хранится
Как вы заметили пришлось все переменные объявить в классе, иначе на вывод в erb были ошибки, которые я не смог понять и исправить. Далее основной элемент приложения это код странички тестов:
# страничка тестов
get '/test' do
if params[:var] == nil
@@mas_test_answer = Array.new(@@kol_testov) { |i| -1}
# заносим случайные вопросы в массив @@mas_test_number
@@mas_test_number[0] = Random.rand(@@test_hash.length)
@@mas_test_number.each_index do |i|
begin
flag = true
buf = Random.rand(@@test_hash.length)
0..i.times do |j|
if @@mas_test_number[j]==buf
flag = false
end
end
if flag
@@mas_test_number[i] = buf
end
end until flag==true
end
@@test_number = 0;
# заносим случайные варианты ответов в массив @@mas_random_variants
@@mas_random_variants = Array.new(@@kol_testov)
@@mas_random_variants.each_index do |i|
@@mas_random_variants[i] = Array.new(@@test_hash[@@mas_test_number[i]]["answers"].size)
end
@@mas_random_variants.each_index do |i|
@@mas_random_variants[i][0] = Random.rand(@@test_hash[@@mas_test_number[i]]["answers"].size)
@@mas_random_variants[i].each_index do |j|
begin
flag = true
buf = Random.rand(@@test_hash[@@mas_test_number[i]]["answers"].size)
0..j.times do |k|
if @@mas_random_variants[i][k]==buf
flag = false
end
end
if flag
@@mas_random_variants[i][j] = buf
end
end until flag==true
end
end
else
#сохраняем выбранный вариант ответа в массив @@mas_test_answer
@@mas_test_answer[@@test_number] = params[:var].to_i
#если возможно выдаем след вопрос
if @@test_number != @@kol_testov - 1
@@test_number += 1
end
end
erb :test
end
По условию params[:var] == nil
мы определяем что пользователь впервые на страничке и «готовим» все необходимое(случайно выбираем тесты из базы, случайно «перемешиваем» варианты ответов и создаем массив для хранения ответов), иначе записываем выбранный пользователем ответ в массив. Весь функционал приложения построен на get запросах, а много путаницы в следствии того, что писалось оно в режиме «лишь бы работало». К примеру если пользователь переходит по ссылке http://localhost:4567/test?var=0 то в массиве ответов на текущий вопрос будет установлено значение 0.
Рассмотрим код странички тестов
@@test
<!DOCTYPE html>
<html>
<head>
<title>Тесты</title>
</head>
<body>
<div>
<h2> Вопрос №<%= @@test_number +1 %> <h2>
<h3>
<%= @@test_hash[@@mas_test_number[@@test_number]]["question"] %>
</h3>
</div>
<p>
<form method="get" action="/test">
<% @@test_hash[@@mas_test_number[@@test_number]]["answers"].each_index do |i| %>
<input type="radio" name="var" value="<%= @@mas_random_variants[@@test_number][i] %>">
<%= @@test_hash[@@mas_test_number[@@test_number]]["answers"][@@mas_random_variants[@@test_number][i]] %>
<% end %>
<input type="submit" value="Ответить"/>
</form>
</p>
<div>
<input type="button" name="next_question" value="Предыдущий вопрос" onclick="location.href='/test/pred'">
<% @@mas_test_number.each_index do |i| %>
<a href='/test/question/<%= i + 1 %>'> № <%= i + 1 %> </a>
<% end %>
<input type="button" name="pred_question" value="Следующий вопрос" onclick="location.href='/test/next'">
</div>
<input type="button" name="result" value="Завершить тестирование" onclick="location.href='/test/result'">
</body>
</html>
Как вы заметили вставка кода на страничку проиcходит при помощи erb следующим образом <%= #код с выводом данных %>
и <% код без вывода данных %>
. На самой страничке вопрос, варианты ответов(radiobutton), ссылки на все вопросы. кнопки навигации по тестам и кнопка завершения тестирования, которая направляет пользователя на страничку результатов теста.
Работа кнопок навигации и ссылок на вопросы:
# ссылки на каждый вопрос
get '/test/question/:id' do
@@test_number = params[:id].to_i - 1
erb :test
end
# следующий вопрос
get '/test/next' do
if @@test_number != @@kol_testov - 1
@@test_number += 1
end
erb :test
end
# предыдущий вопрос
get '/test/pred' do
if @@test_number != 0
@@test_number -= 1
end
erb :test
end
Осталось разобрать код странички результатов теста которая подсчитывает итоги
# страничка результатов
get '/test/result' do
@@ball = 0
@@answers = 0
#подсчет правильных ответов
@@mas_test_answer.each do |i|
if i == 0
@@ball += 1
end
if i != -1
@@answers += 1
end
end
@@procent_tru_answers = (100/@@kol_testov) * @@ball
erb :result
end
И код на html + erb
@@result
<!DOCTYPE html>
<html>
<head>
<title>Результат</title>
</head>
<body>
<h1> Результаты вашего теста </h1>
<div>
<table cellspacing="2" border="1" cellpadding="5">
<tr> <td> № </td> <td> Вопрос </td> <td> Ваш ответ </td> <td> Правильный ответ </td> <tr>
<% @@mas_test_answer.each_index do |i| %>
<tr>
<td> <%= i+1 %> </td>
<td> <%= @@test_hash[@@mas_test_number[i]]["question"] %> </td>
<td> <%= if (@@mas_test_answer[i] == -1)
@@not_answer
else @@test_hash[@@mas_test_number[i]]["answers"][@@mas_test_answer[i]] end %> </td>
<td> <%= @@test_hash[@@mas_test_number[i]]["answers"][0] %> </td>
<tr>
<% end %>
</table>
</div>
<div>
<h3> Количество тестов = <%= @@kol_testov %> </h3>
<h3> Количество ответов = <%= @@answers %> </h3>
<h3> Количество правильных ответов = <%= @@ball %> </h3>
<h3> Процент правильных ответов = <%= @@procent_tru_answers %> %</h3>
<div>
<div>
<p> Этот сайт предназначен для тех кто хочет проверить свои знания.
</p>
</div>
<input value="Пройти снова" name="test_begin" onclick="location.href='/test'" type="button">
</body>
</html>
Я понимаю что данное приложение легче написать с нуля и правильно, нежели понять или сопровождать это. Язык ruby я начал изучать на этом приложении ровно как движок sinatra, язык разметки erb и формат json, поэтому прошу строго не судить за то, что и как использовал.
В дальнейшем планируется переход от sinatra к ror, от json к полноценной базе данных, от erb к haml, от однотипных вопросов(radiobutton) к вопросам 5-6 типов, от тестов к игре и плюс дизайн с версткой.
Приложение в рабочем виде можно увидеть на сайте.
Репозиторий на гитхабе.
Автор: Kaspsoft