Sinatraとは
Sinatraは、Webサイト、Webサービス、WebアプリケーションをRubyで作成するためのドメイン固有言語(ドメイン特化言語)である。
Ruby on Railsは多機能で難しいので、まずはSinatraの学習からはじめたほうがいいらしい。
- Sinatraとは
- まずはHello world
- じゃんけんアプリの例
- URLからパラメータを受け取る
- ワイルドカードを使う
- マッチについて
- リクエストの移動
- リダイレクト
- 静的ファイル
- 外部ビューファイル
- ビューへのデータ受け渡し
- フィルタ
- 異なるスコープのself
- 参考
環境:macOS Catalina / Ruby 2.7.1
まずはHello world
sinatra.rbという名前で以下のコードを記述。
require 'sinatra' get '/' do "Hello, world!" end
Terminalでruby sinatra.rb
を実行し、ブラウザを確認するとこうなる。
メソッド 'ルート' do
形式で表現される。この例では、/
パスへのHTTP GETリクエストに応答するようアプリケーションに命令している。
4567はSinatraのデフォルトのポート番号。
じゃんけんアプリの例
require 'sinatra' # ルートを処理する前に、レスポンスをプレーンテキストとして設定し # プレーヤー(とコンピュータ)が出せる有効な手の配列を設定する before do content_type :txt @defeat = {rock: :scissors, paper: :rock, scissors: :paper} # キーも値もシンボルのハッシュ @throws = @defeat.keys # 全キーの配列を返す end get '/throw/:type' do # params[]ハッシュにはクエリ文字列とフォームデータが格納されている player_throw = params[:type].to_sym # プレーヤーが無効な手を指定した場合は、 # アプリケーションを停止してステータスコード403(Forbidden)を返し、 # 有効な手を指定するよう知らせる if !@throws.include?(player_throw) halt 403, "この中から選んでね #{@throws}" end # コンピュータの手をランダムに選択する computer_throw = @throws.sample # プレーヤーとコンピュータの手を比較して結果を表示する if player_throw == computer_throw "あいこだよ。Try again!" elsif computer_throw == @defeat[player_throw] "勝ち!! #{player_throw} beats #{computer_throw}!" else "負け... #{computer_throw} beats #{player_throw}. Better luck next time!" end end
URLからパラメータを受け取る
require 'sinatra' require 'sinatra/reloader' get '/hello/:name' do "hello #{params[:name]}" end
ワイルドカードを使う
require 'sinatra' get '/*' do "You passed in #{params[:splat]}" end
ワイルドカードで渡されたものはすべてparams[:splat]内の配列に格納される。
マッチについて
require 'sinatra' get '/*' do "Hi!" end get '/hello' do "Hello!!" end
これだとHello!!と表示されない。
リクエストの移動
passメソッドを使うと次に有効なマッチを調べる。
require 'sinatra' get %r{/(sp|gr)eedy} do pass if request.path =~ /\/speedy/ "You got caught in the greedy route!" end get '/speedy' do "You must have passed to me!" end
リダイレクト
ステータスコードを使い分けることができる。
require 'sinatra' get '/redirect' do redirect 'http://www.google.com' end get '/redirect2' do redirect 'http://www.google.com', 301 end
デフォルトでは一時的なリダイレクト(コード302)とみなされる。
静的ファイル
publicディレクトリの中に以下の内容でpublic.htmlというファイルを作る。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Static file</title> </head> <body> <h1>This is a static file.</h1> </body> </html>
require 'sinatra' get '/public.html' do 'This is delivered via the route.' end
定義されたルートが静的リソースの名前と衝突する場合、静的リソースが提供される。また、URLからpublicフォルダが削除される。
外部ビューファイル
viewsディレクトリの中にindex.erbという名前で以下のファイルを保存する。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>External template</title> </head> <body> <h1>外部ビュー</h1> </body> </html>
require 'sinatra' get '/index' do erb :index end
例えば、viewsの中のuserサブディレクトリでname.erbファイルとprofile.erbファイルを検索する方法。
require 'sinatra' get '/:user/name' do erb '/user/name'.to_sym end get '/:user/profile' do erb :'/user/profile' end
シンボルの作成方法はどちらでもOKだが、to_sym
を利用する方法が一般的のよう。
ビューへのデータ受け渡し
インスタンス変数を使ってビューと共有することができる。
views/home.erb↓
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>instance variables</title> </head> <body> <h1>Hello, <%= @name %>!</h1> </body> </html>
require 'sinatra' get '/home' do @name = 'Random User' erb :home end
評価対象の文(インスタンス変数の表示、変換処理の実施など)は<%= %>
タグで囲み、ループなどの制御文は<% %>
で囲む。
フィルタ
ルートが実行される前後にリクエストとレスポンスを変更する機能。 以下の例では、beforeフィルタを使用してルートを処理する前にインスタンス変数を設定している。
require 'sinatra' before do @before_value = 'foo' end get '/' do "before_value = #{@before_value}" end after do puts "After filter called." end
異なるスコープのself
require "sinatra" outer_self = self get '/' do content_type :txt "outer self: #{outer_self}, inner self: #{self}" end
ルーティングブロック内のすべてのメソッド呼び出しがSinatra::Applicationクラスのインスタンスに送信されることがわかる。また、外側のスコープはmainである。
参考
ーーー追記ーーー
続いて、課題でSinatraを使ってメモアプリを作った。