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 '/question/:answer_id' do # get_first_rowメソッドで、SELECTした結果の最初の行だけを得る # answer_idが正しければ {"answer_id"=>"リクエストされたID", "name"=>nil, "message"=>nil}、 # 誤っていればnilになる answer = db.get_first_row(<<-SQL, answer_id: params['answer_id']) SELECT answer_id, name, message FROM answers WHERE answer_id = :answer_id; SQL # もしDBに登録されていないanswer_idが来た場合、403を返し終了する。 halt 403 unless answer # セッションIDにanswer_idを追加。 session['answer_id'] = answer['answer_id'] # 回答フォームを生成し返す。 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