記事内で紹介する商品を購入することで、当サイトに売り上げの一部が還元されることがあります。
「一問一答アプリ × ChatGPT」
先日、ChatGPTを活用して一問一答アプリケーション「情報1 一問一答トレーニングGYM」を開発したことをお伝えしました。
▶︎こちらの記事で紹介しています。
【ChatGPTと開発】高校「情報1」一問一答アプリ私が開発したこのアプリは、ChatGPTの力を借りながら、実装していきました。
この記事では、一問一答アプリ × ChatGPTの開発の舞台裏や、実際の活用方法について詳しく解説します。
今回は
- JavaScriptでリロードを禁止する機能の実装
を実装するにあたって、どのように役立ったのか、その様子を紹介します!
ぜひこのシリーズの記事をチェックして、一問一答アプリの新たな魅力とChatGPTとの相乗効果を体感してください!
ブラウザで再読み込み(リロード)をすると、エラーが出てしまう問題が発生していました。
基本的にリロードをしなくても一問一答機能は使えますが、ユーザーがリロードすることは考えられますので、想定しておきたいところです。
そもそも、一問一答を行う際のHTTPメソッドはpostに設定しているにも関わらず、リロードをした際にはGETメソッドでリクエストが送られることが原因。
できることならリロードを禁止できないかと思い、chatGPTと相談してみました。
以下の要件を満たすコードを作ってもらえますか?
▼要件:
- ブラウザのリロードを検知するとアラート(確認?)を表示する(JavaScriptで)
- アラートの文章は「再読み込みすすると、問題を再度作成することになります。よろしいですか?」とする
- アラートに対して肯定的なボタンをクリックすると、controllerのaskアクションにpostメソッドで呼び出す
以下は、要件を満たす例のJavaScriptコードとRailsコードです。
window.addEventListener("beforeunload", function(event) {
event.preventDefault();
event.returnValue = "";
const confirmationMessage = "再読み込みすすると、問題を再度作成することになります。よろしいですか?";
event.returnValue = confirmationMessage;
return confirmationMessage;
});
ただ実装すると、ダイアログはでないわ、引き続きGETメソッドでリクエストが送られてしまうわで解決に結びつきません。
いろいろと悩み、四苦八苦した結果、発想を変えて
GETメソッドでのリクエストがあった場合の処理を記述すれば良いのでは?
という発想を転換することにしました。
まずはルーティングの設定です。画面遷移のある#askアクション、#next_questionアクション、#printアクション、#retryアクションについてgetメソッド版のルーティングを設定します。
Rails.application.routes.draw do
(省略)
collection do
get 'choose'
get 'ask'
post 'ask'
get 'next_question'
post 'next_question'
post 'check'
get 'print'
post 'print'
get 'score'
get 'retry'
post 'retry'
end
(省略)
end
続いて、questionコントローラーを設定します。
class QuestionsController < ApplicationController
def ask
if request.get?
render html: '<script>alert("選択内容が解除されトップページに戻ります。");window.location.href = "/";</script>'.html_safe
elsif request.post?
# まずはセッション変数を取得する
# next_questionメソッドで使うため
# session[:asked_question_ids] ||= [] でセッションが未定義なら新しく作るという意味になる
session[:asked_question_ids] ||= []
(省略)
redirect_to root_path, alert: "出題できる問題がありません。"
end
end
end
def next_question
if request.get?
render html: '<script>alert("選択内容が解除されトップページに戻ります。");window.location.href = "/";</script>'.html_safe
elsif request.post?
if session[:question_range] != nil
@question = Question.where(id: session[:question_range]).where.not(id: session[:asked_question_ids]).order("RAND()").first
else
#当メソッドを呼び出す際には最低1回はask~resultメソッドを実行している。そのため、セッションを参考にして分野を指定しながら出題済みの問題を避けて次の問題(インスタンス)を取得できる。
@question = Question.where(genre_id: session[:selected_genre_ids],level_id: session[:selected_level_ids]).where.not(id: session[:asked_question_ids]).order("RAND()").first
end
# session[:asked_question_ids]に取得したインスタンスの問題idを追加格納する。
if @question.present?
session[:asked_question_ids] << @question.id
@choices = @question.choices.includes(:question) #questionとアソシエーション関係なので()の中にはカラム名ではなく関係のあるモデル名にする「_id」は不要
@answer = Answer.find(@question.id)
if session[:question_nums].present?
@question_nums = session[:question_nums]
end
# -1は出題数を調整するため
@asked_question_count = (session[:asked_question_ids].length - 1)
@correct_counts = session[:correct_answers].length
# to_fは浮動小数(float)への変換
@correct_rate = ((@correct_counts.to_f / @asked_question_count.to_f) * 100).round(1)
# 呼び出すビューファイルはaskアクションのビューファイル
render :ask
else
redirect_to score_questions_path
end
end
end
def retry
if request.get?
render html: '<script>alert("選択内容が解除されトップページに戻ります。");window.location.href = "/";</script>'.html_safe
elsif request.post?
# いくつかのセッションをリセットする
session[:asked_question_ids] = []
(省略)
if @question.present?
# 不正解問題のidを出題済みセッションに格納する
session[:asked_question_ids] << @question.id
@choices = @question.choices.includes(:question) #questionとアソシエーション関係なので()の中にはカラム名ではなく関係のあるモデル名にする「_id」は不要
@answer = Answer.find(@question.id)
render :ask
else
redirect_to score_questions_path
end
end
end
def print
if request.get?
render html: '<script>alert("選択内容が解除されトップページに戻ります。");window.location.href = "/";</script>'.html_safe
elsif request.post?
# 出題数をパラムスより取得する
question_count = params[:question_count].to_i
(省略)
end
end
この手法は強引なんですけど、それぞれのアクションに対するURLを直入力した際の対策も同時にできるので、(before_actionなどを使わなくても良い)その点を考えても効果的かと思います。
そして実装できたのがこちら
今回の開発作業で
- JavaScriptでリロードを禁止する機能の実装
を実装することができました。
ChatGPTを利用すると開発がグンと楽になりますね!ChatGPTの可能性を体験してみてはいかがでしょうか?
最後まで読んでいただきありがとうございました。
この記事が少しでも参考になれば幸いです。
それではまたここで会いましょう!
にほんブログ村ブログ村に参加中です。上のバナーをクリックいただくだけで当ブログにポイントが入ります。いつも応援クリックありがとうございます。
Twitter やってます。
新着記事のお知らせをしていますのでぜひフォローしてください!スポンサーリンク