やること
- 問題数合計50問程度からランダムで10問を選び出題する
- ユーザーのログインなしで回答できる
- 回答は全クイズにおいて4択の選択式
- 回答後に正答率を表示
完成イメージ
データベース構成
テーブル名: questions
- content (質問の内容を格納する文字列)
- option1, option2, option3, option4 (選択肢の文字列)
- correct (正解の選択肢を表す整数)
テーブル名: user_answers
- q1_id から q10_id (質問のID)
- q1_yourans から q10_yourans (ユーザーの回答を表す整数)
- q1_isCorrect から q10_isCorrect (ユーザーの回答が正解かどうかを表す真偽値)
作っていく!
モデル作成
コマンドプロンプト
rails g model Question
rails g model User_answer
/db/migrate/~~_create_quesitons.rb
class CreateQuesitons < ActiveRecord::Migration[6.1]
def change
create_table :questions do |t|
+ t.string :content
+ t.string :option1
+ t.string :option2
+ t.string :option3
+ t.string :option4
+ t.integer :correct
t.timestamps
end
end
end
/db/migrate/~~_create_user_answers.rb
class CreateUserAnswers < ActiveRecord::Migration[6.1]
def change
create_table :user_answers do |t|
+ t.integer :q1_id
+ t.integer :q2_id
+ t.integer :q3_id
+ t.integer :q4_id
+ t.integer :q5_id
+ t.integer :q6_id
+ t.integer :q7_id
+ t.integer :q8_id
+ t.integer :q9_id
+ t.integer :q10_id
+
+ t.integer :q1_yourans
+ t.integer :q2_yourans
+ t.integer :q3_yourans
+ t.integer :q4_yourans
+ t.integer :q5_yourans
+ t.integer :q6_yourans
+ t.integer :q7_yourans
+ t.integer :q8_yourans
+ t.integer :q9_yourans
+ t.integer :q10_yourans
+
+ t.boolean :q1_isCorrect
+ t.boolean :q2_isCorrect
+ t.boolean :q3_isCorrect
+ t.boolean :q4_isCorrect
+ t.boolean :q5_isCorrect
+ t.boolean :q6_isCorrect
+ t.boolean :q7_isCorrect
+ t.boolean :q8_isCorrect
+ t.boolean :q9_isCorrect
+ t.boolean :q10_isCorrect
t.timestamps
end
end
end
コマンドプロンプト
rails db:migrate
seedを使って問題を登録します
(中身はてきとーです、自分の好きな問題にしておいてください)
db/seeds.rb
50.times do |i|
Question.create(
content: "テスト用#{i}の問題だよ!",
option1: "テスト用#{i}の選択肢1だよ",
option2: "テスト用#{i}の選択肢2だよ",
option3: "テスト用#{i}の選択肢3だよ",
option4: "テスト用#{i}の選択肢4だよ",
correct: i % 4 + 1,
)
end
コマンドプロンプト
rails db:seed
コントローラ作成
tops編
コマンドプロンプト
rails g controller tops
app/controllers/tops_controller.rb
class TopsController < ApplicationController
def index
end
end
index.html.erbを作成
views/tops/index.html.erb
<h1>Top Page</h1>
<%= link_to "10問クイズに挑戦", quiz_path(1) %>
quizzes編
こっからがちょっとえぐめです
コマンドプロンプト
rails g controller quizzes
app/controllers/quizzes_controller.rb
class QuizzesController < ApplicationController
def show
@q_num = params[:id]
if @q_num != '1'
@user_id = params[:user_id]
end
q_sum = Question.count
rand_num = SecureRandom.random_number(q_sum) + 1
@q = Question.find(rand_num)
end
def create
q_num = params[:q_num].to_i
user_id = params[:user_id].presence
user_ans = user_id ? UserAnswer.find(user_id) : UserAnswer.new
q_attr = "q#{q_num}_"
user_ans[q_attr + 'id'] = params[:q_id].to_i
user_ans[q_attr + 'yourans'] = params[:choice].to_i
user_ans[q_attr + 'isCorrect'] = (Question.find(params[:q_id].to_i).correct == params[:choice].to_i)
user_ans.save
redirect_to q_num == 10 ? result_path(user_id: user_ans.id) : quiz_path(q_num + 1, user_id: user_ans.id)
end
def result
@user_ans = UserAnswer.find(params[:user_id])
end
end
showアクションではクイズの問題をランダムで選出しています
@q_num
は第oo問にあたり、@q
がランダムに選出した問題になります
しかし、ここでは10問選ばれるうちに同じ問題が選ばれてしまう可能性があるので、のちに出てくるUserAnswer
を参照して1度選ばれた問題は選ばれないようにした方がいいかもしれません
(具体的な実装方法はこの記事では記載しておりません)
createアクションでは1問ごとにその結果をUserAnswerに記録していってます
複雑になってしまっているのは第1問の時は、新しくUserAnswerにレコードを追加し、第2問以降は第1問で作成したレコードをupdateする形にしているからです〜〜
ややこしいですwww
views/quizzes/show.html.erb
<h1>第<%= @q_num %>問 <%= @q.content %></h1>
<%= form_with(url: quizzes_path, method: :post) do |f| %>
<%= f.label :選択肢 %><br>
<%= f.radio_button :choice, 1 %> <%= @q.option1 %> <br>
<%= f.radio_button :choice, 2 %> <%= @q.option2 %> <br>
<%= f.radio_button :choice, 3 %> <%= @q.option3 %> <br>
<%= f.radio_button :choice, 4 %> <%= @q.option4 %> <br>
<%= f.hidden_field :q_id, :value => @q.id %>
<%= f.hidden_field :q_num, :value => @q_num %>
<% if @q_num != '1' %>
<%= f.hidden_field :user_id, :value => @user_id %>
<% end %>
<% if @q_num.to_i < 10 %>
<%= f.submit '次の問題へ' %>
<% else %>
<%= f.submit '結果を表示する' %>
<% end %>
<% end %>
views/quizzes/result.html.erb
<h1>結果表示ページ</h1>
<% (1..10).each do |i| %>
<% q_attr = "q#{i}_" %>
<h3>第<%= i %>問 <%= @user_ans[q_attr + 'isCorrect'] ? 'o' : 'x' %> あなたの回答: <%= @user_ans[q_attr + 'yourans'] %> 正解: <%= Question.find(@user_ans[q_attr + 'id'].to_i).correct %> </h3>
<% end %>
<%= link_to "もう1度10問クイズに挑戦", quiz_path(1) %>
resultページは繰り返し処理で簡単に書いてみました〜
最後にroutesを追加します
config/routes.rb
root 'tops#index'
resources :tops, only: %i[index]
resources :quizzes
get '/result' => 'quizzes#result'
以上で終わりです!
複雑やったし、セキュリティ的にもまあまあやばそうな気がしてはいるんですけど、実装優先でやってみました〜
誰かの参考になればなと思います!
それでは、ばいちゃ〜〜〜〜
今回の全体コードはこちら〜