Edited at

Railsで基本情報技術者試験の過去問題サイトを作る(8:自動解答編)


はじめに

ゆる〜く学ぶ。みんなのWeb勉強コミュニティー。 「にゅ〜ぶる会」を運用中です。

https://newburu.github.io/

そこで、何か教育用のコンテンツが欲しいなぁ〜と思い立ち、今回の企画をスタートしました!

Railsで基本情報技術者試験の過去問題サイトを作ります!


最終目標


  • 問題・解答の登録は、Scaffoldで簡易でOK

  • APIを用意して、ランダムに問題を抽出する機能を追加する

  • TwitterBOT、LINEBOT、SlackBOTが出来たら良いな


履歴

1:構築編

  https://qiita.com/newburu/items/ed59f47ac645b19620f6

2:日本語化(i18n)編

  https://qiita.com/newburu/items/4f12fdb61bf6cd601545

3:親子関係、登録編

  https://qiita.com/newburu/items/f2a20289be5ec1fc1b77

4:親子関係、参照編

  https://qiita.com/newburu/items/51b11bd02691efc2cc0d

5:API編

  https://qiita.com/newburu/items/89f9f847a2648bdd006c

6:SlackBOT編

  https://qiita.com/newburu/items/aeeb9acb453da786bd59

7:Herokuデプロイ〜自動化編

  https://qiita.com/newburu/items/0a8bb02e1e8c8fe737c7

8:自動解答編

  本ページ


今回やる事


  • Slackに投稿した問題に、スレッドで解答を投稿する。


Slackのスレッドで投稿します。


1. SlackAPIでのスレッド投稿について理解しましょう。

※参考

 https://api.slack.com/methods/chat.postMessage


  • Slack.chat_postMessageのレスポンスで、tsが返って来ます。

    ※これが、その投稿の識別IDになるようです。

  • 投稿時(Slack.chat_postMessage)のオプション「thread_ts」に、先ほどのtsを指定すると、スレッドとして投稿されるようです。


2. 投稿した履歴を記憶するモデルに追加します。

名前
物理名

備考

問題ID
question_id
数値(integer)

投稿したSlackTS
slack_ts
文字列(string)

ステータス
status
数値(integer)
Enum使う


Modelを作成します。


Scaffold

例) rails g[enerate] model モデル名 カラム名1:データ型1 カラム名2:データ型2 …

$ rails g model History question:references slack_ts:string status:integer


DB作成

$ rake db:migrate



ステータス(status)にEnumの設定を行います。


models/History.rb

class History < ApplicationRecord

belongs_to :question

enum status: {do: 0, done: 1}
end



3. 投稿時に履歴を保存します。

投稿時のタスクに、履歴を保存するロジックを追加します。


lib/tasks/slack_bot.rake

namespace :slack_bot do

desc 'ランダムに問題をSlackに書き込む'
task :random_question => :environment do
  
  〜 中略 〜

# text:出力テキスト、channel:出力先のチャンネル名、username:表示ユーザ名
ret = Slack.chat_postMessage(text: msg, channel: ENV["SLACK_CHANNEL_NAME"], username: ENV["SLACK_BOT_NAME"])

History.create(question: question, slack_ts: ret['ts'], status: :do)
end
end



4. 手動で動かして問題ないか確認しましょう。


手動実行

rake slack_bot:random_question


Historiesテーブルにレコードが追加されればOKです!


5. 解答の投稿タスクを追加しましょう。


lib/tasks/slack_bot.rake

namespace :slack_bot do

desc '解答をSlackに書き込む'
task :answer => :environment do
# 未解答の履歴一覧を取得
History.where(status: :do).each do |history|
question = history.question
answers = question.answers.where(correct: true)

# 解答テキスト
# HACK:ちょっと無理やり感があるので、リファクタ候補
answer_msg = []
first_answer = question.answers.order(:id).first
answers.each do |a|
answer_msg << "#{%w( )[a.id - first_answer.id]}"
end
msg = "【解答】" + answer_msg.join("、")

# thread_ts:投稿先スレッドTS、text:出力テキスト、channel:出力先のチャンネル名、username:表示ユーザ名
Slack.chat_postMessage(thread_ts: history.slack_ts, text: msg, channel: ENV["SLACK_CHANNEL_NAME"], username: ENV["SLACK_BOT_NAME"])

# 解答済みに変更
history.update(status: :done)
end
end
end



6. 確認しましょう

まずは、rakeタスクとして登録されているか確認しましょう。

$ rake -vT

〜 略 〜
rake slack_bot:answer # 解答をSlackに書き込む
〜 略 〜

では、実行!

$ rake slack_bot:answer

Slackを確認し、こんな感じの表示されればOKです!

Slackを確認


7. Herokuにデプロイし、Heroku Schedulerの設定をしましょう。

設定方法については、省略させて頂きますね。

注意点としては、「問題タスク」の後に「解答タスク」を動かすと、即解答してしまうので、

「解答タスク」を実行した後に、「問題タスク」を実行するように設定してください。

※これで、次のタスク実行時に、前回タスクで書き込まれた問題に解答が書き込まれるようになります。


今回はここまで

ありがとうございました!

次回は、またいつになるかわかりませんが…💦

基本情報の問題には、表が含まれる場合がありますので、問題に画像を登録出来るようにしたいと思います。