記事内で紹介する商品を購入することで、当サイトに売り上げの一部が還元されることがあります。
「一問一答アプリ × ChatGPT」
先日、ChatGPTを活用して一問一答アプリケーション「情報1 一問一答トレーニングGYM」を開発したことをお伝えしました。
▶︎こちらの記事で紹介しています。
【ChatGPTと開発】高校「情報1」一問一答アプリ私が開発したこのアプリは、ChatGPTの力を借りながら、実装していきました。
この記事では、一問一答アプリ × ChatGPTの開発の舞台裏や、実際の活用方法について詳しく解説します。
今回は
- 非同期通信での正誤判定機能
という機能を実装するにあたって、どのように役立ったのか、その様子を紹介します!
ぜひこのシリーズの記事をチェックして、一問一答アプリの新たな魅力とChatGPTとの相乗効果を体感してください!
目次
参考にしているwebアプリケーションはページ遷移せずに正誤判定を行ってくれるので、同じような機能を実装したい!ということで、非同期通信で正誤判定ができないか実装してみました。
前回までの開発では問題が表示されるアクションと正誤判定する機能を別のアクションに切り分け、ページ遷移して正誤判定するという流れをとっていました。
Ajaxを利用して実現させていきたいと思います。
実装の詳細な途中経過は割愛しますが、取得した選択肢のid(choice_id)をサーバーへ送ろうとすると
statusコード422が表示され、リクエストがサーバーに届いていないことが判明しました。
調べてみるとターミナルで以下のように表示されています。
一番上のActionController::InvalidauthenticityTokenの部分をchatGPTに相談してみたら、
とわかりやすく説明してくれて、解決するコードまで教えてくれました。
この現象はクロスサイト攻撃に対するセキュリティがrailsではデフォルトで備わっているから。
なので、操作するbutton_toタグからでもトークンを取得できるように変更しました。
chatGPTから教えてもらったのは以下のコードを追記するとこの問題を解決できるとのこと
xhr.setRequestHeader('X-CSRF-Token', token); // トークンをリクエストヘッダーに追加
実装した結果のソースコードがこちらです。
check_answer.js
function check_answer(){
const buttons = document.querySelectorAll(".buttons");
buttons.forEach(function(button){
button.addEventListener("click",function(e){
e.preventDefault();
var token = document.getElementsByName('csrf-token')[0].content;
var choice_id = this.getAttribute('data-choice-id');
const xhr = new XMLHttpRequest();
xhr.open('POST', '/questions/check', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.setRequestHeader('X-CSRF-Token', token); // トークンをリクエストヘッダーに追加
xhr.onload = function() {
if (xhr.status === 200) {
// 正誤判定の結果を表示
var data = JSON.parse(xhr.responseText);
var result = data.result ? '正解!' : '不正解...';
document.querySelector('#result').textContent = result;
}
else {
console.error(xhr.statusText);
}
};
xhr.send('choice_id=' + encodeURIComponent(choice_id));
});
});
};
window.addEventListener('load',check_answer);
コントローラーはこちら
questions_controller.rb
def check
# binding.pry
# 選択された値の正誤を判定
choice = Choice.find(params[:choice_id])
if choice.is_answer == 1
result = true
else
result = false
end
# 正誤判定の結果をJSON形式で返す
render json: { result: result }
end
ビューファイルも(現時点で)こんな感じ
<div class="contents row">
<div class="question_id">
<%= "問題 #{@question.id}"%>
</div>
<div class="sentense">
<p>次の問題文の答えとして最も適している語句を選びなさい。</p>
</div>
<div class="question_text">
<%= @question.text%>
</div>
<div class="choices">
<h4><解答一覧></h4>
<p>ア. <%= @choices[0].choice%></p>
<p>イ. <%= @choices[1].choice%></p>
<p>ウ. <%= @choices[2].choice%></p>
<p>エ. <%= @choices[3].choice%></p>
<div class="button-list" style="display:flex;" id="button-list">
<%= button_to "ア", "/questions/result", {method: :post, params: {choice_id: @choices[0].id, question_id: @question.id}, class: "buttons",data: { "choice-id" => @choices[0].id, "choice-name" =>"ア", "question-id" => @question.id},"csrf-token" => form_authenticity_token }%>
<%= button_to "イ", "/questions/result", {method: :post, params: {choice_id: @choices[1].id, question_id: @question.id}, class: "buttons",data: { "choice-id" => @choices[1].id, "choice-name" =>"イ", "question-id" => @question.id},"csrf-token" => form_authenticity_token }%>
<%= button_to "ウ", "/questions/result", {method: :post, params: {choice_id: @choices[2].id, question_id: @question.id}, class: "buttons",data: { "choice-id" => @choices[2].id, "choice-name" =>"ウ", "question-id" => @question.id},"csrf-token" => form_authenticity_token }%>
<%= button_to "エ", "/questions/result", {method: :post, params: {choice_id: @choices[3].id, question_id: @question.id}, class: "buttons",data: { "choice-id" => @choices[3].id, "choice-name" =>"エ", "question-id'" => @question.id},"csrf-token" => form_authenticity_token }%>
</div>
<%= button_to "解答を見る", "/questions/result", {method: :post, params: {choice_id: 0, question_id: @question.id}, id: "seeAnsButton", class: "buttons",data: { "choice-id" => 0,"choice-name" =>"-" , "question-id'" => @question.id},"csrf-token" => form_authenticity_token }%>
<div id="result"></div>
<p>------</p>
<p><%= link_to '問題選択へ戻る', root_path, method: :get %>
</div>
そして実装後の挙動はこんな感じです。
これでページ遷移せずに正誤判定機能を実装できました
ちなみに情報ではあるのですが、下地作りのためにも、Ajaxで正誤判定を実現するためにchatGPTにもコード作成を依頼してみました。その結果が以下です。
以下の要件を満たすコードをrailsで作成してください。必要に応じてjavascriptを使用してもかまいません▼要件・選択された回答に含まれた値(この値を仮にchoice_idとする)をparamsとして送信する・その値を用いてAjaxでサーバーと接続し正誤判定する。・正誤判定の結果はjavascriptで表示する
以下は、要件を満たす可能性があるコード例です。詳細な実装については、環境や要件によって異なるため、必要に応じて変更してください。
HTML側
<!-- 回答のラジオボタンを作成 -->
<% @question.choices.each do |choice| %>
<div>
<%= radio_button_tag 'choice_id', choice.id, false %>
<%= label_tag "choice_#{choice.id}", choice.content %>
</div>
<% end %>
<!-- 「回答する」ボタンを作成 -->
<button id="submit-btn">回答する</button>
<!-- 回答の正誤を表示する要素を作成 -->
<div id="result"></div>
JavaScript側
// 「回答する」ボタンをクリックしたときの処理
$('#submit-btn').on('click', function() {
// 選択された値を取得
var choice_id = $('input[name="choice_id"]:checked').val();
// Ajaxで正誤判定を実行
$.ajax({
type: 'POST',
url: '/questions/check',
data: { choice_id: choice_id },
dataType: 'json'
}).done(function(data) {
// 正誤判定の結果を表示
var result = data.result ? '正解!' : '不正解...';
$('#result').text(result);
});
});
Rails側
rubyCopy code
# config/routes.rbにルーティングを追加
post '/questions/check', to: 'questions#check'
# app/controllers/questions_controller.rb
class QuestionsController < ApplicationController
def check
# 選択された値の正誤を判定
choice = Choice.find(params[:choice_id])
result = choice.correct?
# 正誤判定の結果をJSON形式で返す
render json: { result: result }
end
end
chatGPTが提示してくれたコードも非常に参考になりました!
今回の開発作業で
- 非同期通信での正誤判定機能
を実装することができました。
ChatGPTを利用すると開発がグンと楽になりますね!ChatGPTの可能性を体験してみてはいかがでしょうか?
最後まで読んでいただきありがとうございました。
この記事が少しでも参考になれば幸いです。
それではまたここで会いましょう!
にほんブログ村ブログ村に参加中です。上のバナーをクリックいただくだけで当ブログにポイントが入ります。いつも応援クリックありがとうございます。
Twitter やってます。
新着記事のお知らせをしていますのでぜひフォローしてください!スポンサーリンク