今日はsinatraについて学んだことを書いていきます。getメソッドとpostメソッドでの簡単な登録フォームの作成だけです。あとXSSやSQLインジェクションにも少し触れていきます。
まずは基本のhello worldから
require 'sinatra'
get '/' do
'hello world'
end
$ ruby hello.rb
とコマンドラインで実行した後にhttp://localhost:4567/ にアクセスするとhello worldが表示されるはずです。
これだけでは自分の表示したいテキストをそのまま表示させるだけです。これをhtmlを使って体裁を整えるにはerbファイルを使います。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8"/>
<title>hello</title>
</head>
<body>
<div>
hello world
</div>
</body>
</html>
そして元のrbファイルを
require 'sinatra'
get '/' do
erb:hello
end
とすれば自分の好きなようにhtmlで文章を配置できます。
次はユーザーからのパラメータを受け取ってサイト内に反映するプログラムです。getメソッドを使います。
require 'sinatra'
get '/hello/:name' do
"こんにちは #{params[:name]}さん"
end
このプログラムでは2行目の:nameにユーザーから受け取るパラメータが入り、例えばhttp://localhost:4567/hello/KB というURLにアクセスするとKBの部分がパラメータとなり、「こんにちはKBさん」と表示されます。
次は同じことをpostメソッドを使ってフォーム入力できるようにしてみます。
require 'sinatra'
get '/form' do
erb :form
end
post '/hello' do
@name=h(params[:name])
erb :hello
end
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8"/>
<title>名前入力</title>
</head>
<body>
<form method="post" action="/hello">
<input type="text" name="name">
<input type="submit" value="送信">
</form>
</body>
</html>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8"/>
<title>hello</title>
</head>
<body>
<div>
こんにちは<%=@name%>さん
</div>
</body>
</html>
これはhttp://localhost:4567/form にアクセスすると名前の入力フォームと送信ボタンが表示され、名前を入力して送信ボタンをクリックするとhttp://localhost:4567/hello に飛んで「こんにちは○○さん」と表示されます。
さてこの入力フォームをDBと合わせて使うことで簡単な登録サイトや掲示板のようなものを作成することができます。ActiveRecordを使います。DB、テーブルの作成等については割愛します。
require "sinatra"
require 'active_record'
config = YAML.load_file( './database.yml' )
ActiveRecord::Base.establish_connection(config["db"]["development"])
class Prefecture < ActiveRecord::Base
end
get "/" do
@prefectures = Prefecture.order("id desc").all
erb :index
end
post "/new" do
Prefecture.create({:name => params[:name],:gender => params[:gender],:prefecture => params[:prefecture]})
redirect '/'
erb :index
end
<!DOCTYPE html>
<html lang="ja">
<head>
<mata charset="utf-8">
<title>Add</title>
</head>
<body>
<h2>Data</h2>
<ul>
<% @prefectures.each do |prefecture| %>
<li data-id= "<%= prefecture.id %>">
<%= prefecture.name %>
<%= prefecture.gender %>
<%= prefecture.prefecture %>
</li>
<% end %>
</ul>
<h2>Add new</h2>
<form method="post" action="/new">
<p><input type= "text" name="name"></p>
<p>
<input type="radio" name="gender" value="男性" required>男性
<input type="radio" name="gender" value="女性">女性
</p>
<p>
<select name="prefecture">
<option value="東京都">東京都</option>
<option value="神奈川県">神奈川県</option>
<option value="愛知県">愛知県</option>
<option value="大阪府">大阪府</option>
<option value="福岡県">福岡県</option>
<option value="北海道">北海道</option>
</select>
</p>
<p><input type= "submit" value="登録"></p>
</form>
</body>
</html>
この例では名前を入力、性別、住所を選択してDBにデータを入れ、それを表示してくれます。ページの仕組みとしてはhttp://localhost:4567/ にDataとAdd newがあり、Add newにデータを入力するとhttp://localhost:4567/new でDBに登録してそのまま
http://localhost:4567/ に帰ってくることになります。これで登録する情報をコメントなどにすれば簡単な掲示板ができあがりますね。
しかしこのようにユーザーからパラメータを受け取る際には気を付けることがあります。
https://railsguides.jp/security.html
詳しくはこのページを見てほしいんですが、簡単に言えばパラメータにサイトにとって有害なスクリプトを埋め込むことで有害なスクリプトを実行させたり、SQLクエリを入れることでDBの情報を抜き出したりすることができてしまうのです。
例えば最初に挙げた例の名前入力フォームに
<script><alert a><script>
などと入れると警告文が表示されていまいます。
helpers do
def h(text)
Rack::Utils.escape_html(text)
end
end
をrbファイルに入れるとhtmlの入力を回避してくれるみたいです。SQLインジェクションについては例が思いつかないので割愛しますが、webサイトを作る際にはこのようなセキュリティの面にも十分注意が必要ですね。