目次
- はじめに
- なぜ作ろうと思ったか
- 使ってる技術
- 同じようなサービスを作りたい人のために実装を紹介
- 1日に1回、指定の時間に問題を切り替えて表示する
- 質問箱風なOGP画像を生成
- これから
- 最後に
はじめに
Qdash という1日1問形式の SQL 学習サービスを作りました。
問題画面
![スクリーンショット 2019-05-21 12.18.08.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F38580%2F3e563b30-1a14-bf1f-b987-8f1a5a898d5b.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=46d98d74f0da4c923f679215cfcef8d0)
回答画面
![スクリーンショット 2019-05-21 12.18.37.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F38580%2Fb43544fa-9da5-c51b-1e1b-3410a35da041.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=0282a5c17d07bf5dcbdb03b4e53d9f28)
なぜ作ろうと思ったか
とあるデータを見たいけど、いつも SQL を書ける人にお願いしている。
勉強はしたいが、中々勉強する時間が取れない。
と思ってるディレクター、営業、マーケターの方!!
でも1日の中でも隙間時間はありますよね?
その隙間時間に問題を解き、SQL は任せて!と自信を持って言えるようになりませんか?
というのがサービスのコンセプトです。
使っている技術
・ Ruby
・ Rails
・ ServiceWorker / Webpush
・ Heroku
Rails / Heroku で手早く作りました。
push 通知をするために ServiceWorker と Webpush にも挑戦しました。 (この記事では触れません)
実装紹介
似たようなサービスを作りたい人のために実装をいくつか紹介します!
1日に1回、指定の時間に問題を切り替えて表示する
SQL を学びたい人にとって負担にならないように1日1問という仕様にしました。
あなたならどのように実装しますか?
今回は Cookie と Heroku scheduler を使って実装してみました。
class HomeController < ApplicationController
def index
@question = today_question
delete_cookie_if_question_changed
@answer = Answer.find_by(id: answer_id)
end
private
# flesh set by scheduler.rake
def today_question
today_question = TodayQuestion.last || TodayQuestion.create_randomly
today_question.question
end
def delete_cookie_if_question_changed
answer = @question.answers.find_by(id: answer_id)
cookies.delete('answer_id') if answer.nil?
end
def answer_id
cookies['answer_id']
end
end
回答をした際に cookie をセットします。
class AnswersController < ApplicationController
def create
answer = Answers::Factory.build(answer_choice_params)
if answer.save
cookies['answer_id'] = answer.id
redirect_to root_path
else
redirect_to root_path, notice: '回答に失敗しました。'
end
end
private
def answer_choice_params
params.permit(:answer_choice_id)
end
end
Heroku scheduler で1日1回、今日の問題をDBに登録しています。
時間と実行するコマンドはアドオンを入れた後に Heroku の管理画面から設定することができます。
# sheduler.rake
task set_question_randomly: :environment do
TodayQuestion.create_randomly
end
昨日と同じ問題が出たらテンションが下がるのでそれは避けるようにしています。
class TodayQuestion < ApplicationRecord
belongs_to :question
def self.create_randomly
question = nil
loop do
last_question = TodayQuestion.last.question
question = Question.pick_randomly
break if last_question.id != question.id
end
create(question: question)
end
end
質問箱風なOGP画像を生成
続いて、質問箱風な OGP の生成処理です。
問題の作成時に問題のタイトルを画像に書き込み、画像を S3 にアップロードします。 (active_storage を利用)
そして、シェアした時に作成した問題文が書かれたOGP画像が表示されるようにします。
# Gemfile
gem 'mini_magic'
class OgpImageGenerator
def initialize(question: question)
@question = question
end
def generate
image = load_base_image
image.combine_options do |c|
c.gravity 'West'
c.pointsize 30
c.draw "text 55,0 '#{title}'"
c.size "70x"
c.fill '#000'
c.font Rails.root.join('public', 'hiraginokakugoW6.ttc').to_s
c.interline_spacing 10
c.kerning 4
end
image
end
private
def title
ApplicationController.helpers
.sanitize(@question.title)
.chars.each_slice(15)
.map(&:join)
.join("\n")
end
def load_base_image
MiniMagick::Image.read(Rails.root.join('public', 'images', 'ogp_base.png'))
end
end
class Question < ApplicationRecord
..
before_save :generate_ogp_image
before_update :generate_ogp_image
has_one_attached :ogp_image
def generate_ogp_image
return unless self.will_save_change_to_title?
ogp_image_path = OgpImageGenerator.new(question: self).generate.path
file = File.open(ogp_image_path)
self.ogp_image.attach(
io: file,
filename: "question_ogp_image_#{id}_#{SecureRandom.urlsafe_base64}.png", content_type: "image/png"
)
file.close
end
end
問題を作成すると、このような OGP 画像が自動で生成されます。
これから
ログイン機能とコース機能を作って問題を解けるようにしたいと思っています。
ログインしていなくても問題を解くことができる一方で、熱量の高い人はログインしてまとまった時間で勉強できたら良いですね。
実は一番大変なのは機能の実装より SQL の問題を作ることだったりしますw
最後に
詳細な使い方については note に書いているので見ていただけたら幸いです。
https://note.mu/usabdelah/n/n0b7f8fd30ed5
Qdash で学んだことを活かして実務で SQL を書き、
データの可視化をやっていく人が増えたらいいなと思っています。
ぜひ、Qdash で SQL の問題を解いてみてください。