require 'sinatra'
require 'sqlite3'
# 乱数生成ライブラリを読み込む
require 'securerandom'
db = SQLite3::Database.new('answers.db')
#db.results_as_hash = true #ハッシュ化。配列の何番とか分からないから。
# セッション機能を有効化
enable :sessions
# セッション秘密鍵を生成
# この鍵でセッション情報が署名され、ブラウザに返される。
# Webアプリ再起動で鍵が新しくなってしまい全てのセッションが失われるため、
# 固定したい場合はここを固定の秘密鍵に置きかえる。
set :session_secret, SecureRandom.hex(64)
# セッションの有効期限を30日に設定
set :sessions, :expire_after => 60 * 60 * 24 * 30
# クッキーを他のドメインのWebサイトには送らない
set :sessions, :same_site => 'Strict'
# 投稿された名前とメッセージの一覧を返す。
get '/' do
# 名前とメッセージが未投稿のメッセージ以外をSELECTする
answers = db.execute(<<-SQL)
SELECT name, message
FROM answers
WHERE name IS NOT NULL
AND message IS NOT NULL;
SQL
erb(:answers, locals: {'answers' => answers})
end
get '/answers.json' do
# 名前とメッセージが未投稿のメッセージ以外をSELECTする
answers = db.execute(<<-SQL)
SELECT name, message
FROM answers
WHERE name IS NOT NULL
AND message IS NOT NULL;
SQL
json(answers)
end
# 回答フォームを返す。
get '/question/:answer_id' do
# get_first_rowメソッドで、SELECTした結果の最初の行だけを得る
# answer_idが正しければ {"answer_id"=>"リクエストされたID", "name"=>nil, "message"=>nil}、
# 誤っていればnilになる
answer = db.execute(<<-SQL, answer_id: params['answer_id'])[0]
SELECT answer_id, name, message
FROM answers
WHERE answer_id = :answer_id;
SQL
# もしDBに登録されていないanswer_idが来た場合、403を返し終了する。
unless answer
halt 403
end
# セッションIDにanswer_idを追加。
session['answer_id'] = answer['answer_id']
# 回答フォームを生成し返す。
pp answer
erb(:question, locals: answer)
end
# 回答を受信し、お礼ページを返す。
post '/answer' do
# 正常なセッション情報を持たない場合、403を返し終了する。
halt 403 unless session['answer_id']
# 入力された情報とセッションのanswer_idを元にDBを更新。
db.execute(<<-SQL, answer_id: session['answer_id'], name: params['name'], message: params['message'])
UPDATE answers
SET name = :name, message = :message
WHERE answer_id = :answer_id;
SQL
erb(:answer, locals: {'answer_id' => session['answer_id'] })
end
# なんらかのエラーが発生し、halt 403が呼ばれたらここに到達
error 403 do
'アクセスが拒否されました。'
end