Ruby
Sinatra

SinatraでとりあえずWebアプリを立ち上げてみる

2018-11-27 上から順番に内容を更新中です。大まかな記事内容は変わりません。

概要

始めよう - Sinatraで自学自習するよ、って人には物足りないかもしれません。
各項目での所要時間は自身の適当な経験にもとづき記載しておきました。

この記事でやること、やらないこと

  • とりあえずWebアプリをローカル端末で起動し、表示してみる(GET)
  • フォームに入力して登録(POST)、とかまではしません(よってDBは使用しません)
  • URLに値を指定し、それを画面に表示してみる、はやります

想定する対象者

  • Webアプリとか自分で動かしたことないです、的な方
  • Ruby on Railsで挫折しました、的な方
  • 想定作業時間
    • 30〜60分

用意するもの

なるべくあたらしいものをを使用すれば特に問題ないです。
参考にバージョンも記載しておきます。

  • Ruby
    • ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin18]
  • gem
    • bundler
      • Bundler version 1.17.1
      • gemの管理に使用します
    • sinatra
      • 2.0.4
      • Webアプリケーションフレームワーク
    • sinatra-contrib
      • 2.0.4
      • sinatraでの開発時に便利な機能とかを追加できる
  • お好みのエディタ
    • メモ帳などでもなんとかなりますが私はVisual Studio Codeを使用

1. とにかく立ち上げてみる

所要時間:5〜10分

1.1 ディレクトリの作成とbundle init

適当なディレクトリを作ってそこへ移動します。

mkdir try_sinatra
cd try_sinatra

bundler使用するためbundle initを実行します。
するとGemfileというファイルが作成されます。

$ tree
.
└── Gemfile  <<= このファイル

0 directories, 1 file

1.2 gemの追加とインストール

Gemfileに下記を追記するか

./Gemfile
gem 'sinatra'

bundle addコマンドでsinatraを追加します。

bundle add sinatra --skip-install

引き続きgemのインストールを行います。

bundle install --path vendor/bundle

bundle add時の--skip-installオプションは無くても構いませんが、
その場合Gemfileへの追加とgemのインストールを行います。
上記によりシステムグローバルにsinatraがインストールされます。
(bundle configなどの設定をしていない場合など)
実際の開発時はアプリケーション(プロジェクト)ごとに分けることが推奨されます。
またbundle install時の--pathオプション(インストール先の指定)についても同様の理由から指定が推奨されます。
なお、bundlerの詳細については下記の記事など参考にしてください。
Bundlerの使い方 - Qiita

1.3 アプリケーションの作成と起動

Rubyのファイルを作ります。

touch app.rb

上記で作成したファイルに下記のように記載します。

./app.rb
require 'sinatra'

get '/' do
  'hello'
end

続いてsinatraを起動します。

bundle exec ruby app.rb

bundlerを使用しているため、単にruby app.rbではなく
bundle exec ruby app.rbとなります。

参考までにターミナルには下記のように表示されていると思います。

$ bundle exec ruby app.rb
[2018-11-27 23:26:03] INFO  WEBrick 1.4.2
[2018-11-27 23:26:03] INFO  ruby 2.5.1 (2018-03-29) [x86_64-darwin18]
== Sinatra (v2.0.4) has taken the stage on 4567 for development with backup from WEBrick
[2018-11-27 23:26:03] INFO  WEBrick::HTTPServer#start: pid=61737 port=4567

ブラウザで下記にアクセスします。

http://localhost:4567

「hello」と表示されていれば成功です。

補足: 画面に表示される内容について

ちなみに下記のように変更すると

get '/' do
 'hello'
 'good bye' # この行を追加
end

「good bye」のみが表示されます。
つまりgetメソッドの最後の値(戻り値)が表示されます。

ちょっと便利にしてみる

所要時間:5〜10分

まずはapp.rbの内容を変えてみる

require 'sinatra'

get '/' do
  'how are you?'
end

ブラウザをリロードしても表示内容が変化しないはずです。
変更を反映するためにはsinatraを再起動する必要があります。
しかし、変更の度に再起動は面倒なので下記のように変更します。

sinatra/reloaderの導入

※起動したアプリは一旦停止してから行います

Gemfileに下記を追記します。

gem 'sinatra'
gem 'sinatra-contrib' # この行を追加

その後に再度bundle installを実施します。
次にapp.rbを編集します。

require 'sinatra'
require 'sinatra/reloader' # この行を追加。sinatra-contribはこのために必要

get '/' do
  'how are you?'
end

再度sinatraを起動します

bundle exec ruby app.rb

sinatra/reloaderの追加後は、app.rbの変更後にいちいちsinatraを再起動する必要がなくなります。
試しにアプリは起動したままで、下記のように変更してみす。

require 'sinatra'
require 'sinatra/reloader'

get '/' do
  'fine!' # ここを変更
end

ブラウザのリロードで「fine!」と表示されればOKです。
これで変更の度にアプリの再起動の必要がなくなります。

sinatraのルーティングとか追加してみる

所要時間:5〜10分

単純にルーティングを追加してみる

require 'sinatra'
require 'sinatra/reloader'

get '/' do
  'how are you?'
end

# ここから
get '/path/to' do
  "this is [/path/to]"
end
# ここまでを追加

ブラウザでアクセス
http://localhost:4567/path/to

この要領で必要なルートを追加していき、表示するページを追加していきます。
ただ、追加時の注意として記述した順(上から順)にマッチングされるのでその点は注意が必要です。

例えば、get '/path/*'の記載位置より下に
get '/path/to'を書いて、
http://localhost:4567/path/to
にアクセスしても、先にget '/path/*'にマッチするため、
get '/path/*'の内容が表示されます。
パスの指定にワイルドカードなどを使う場合は注意してください。

静的ファイルの追加とアクセス

ルートディレクトリ配下に下記のディレクトリを作成します

mkdir public

そこにhtmlファイルを配置してみます。

echo "this is html file." > ./public/test.html

ブラウザでアクセス
http://localhost:4567/test.html
htmlの内容が表示されます。

つまりpublic配下はurlの「/」以下にマッピングされます。
cssやjsなどもpublic配下に置くことで参照できます。

app.rbとコンフリクトした場合は/publicの方が優先のようです。

URLから値を取得する

app.rbを下記のように変更してみます。

require 'sinatra'
require 'sinatra/reloader'

get '/' do
  'how are you?'
end

get '/path/to' do
  "this is [/path/to]"
end

# ここから
get '/hello/*' do |name|
  "hello #{name}. how are you?"
end
# ここまでを追加

ブラウザでアクセス

ワイルドカード部分が変数nameに格納されます。
値の取得方法は他にもやりかたがあるのでそれは始めよう - Sinatraなどで確認してください。

VIEWを使う

所要時間:10〜30分

ToDo: 時間ができたら書く。
始めよう - Sinatra ビュー / テンプレート

erb

app.rbを下記のように変更します。

require 'sinatra'
require 'sinatra/reloader'

get '/' do
  'how are you?'
end

get '/path/to' do
  "this is [/path/to]"
end

get '/hello/*' do |name|
  "hello #{name}. how are you?"
end

# ここから
get '/erb_template_page' do
  erb :erb_template_page
end
# ここまでを追加

さらにディレクトリとファイルを追加します。

mkdir views
touch views/erb_template_page.erb

上記erbファイルに下記のように追加します。

<%= Time.now %>

ブラウザでアクセス
http://localhost:4567/erb_template_page

現在時刻が表示されれば成功です。
erbの詳細などは省略します。

markdown

redcarpetを導入します(ほかにもあるけど)
Gemfileを下記のように追記。

gem 'sinatra'
gem 'sinatra-contrib'
gem 'redcarpet' # この行を追加

bundle installを実行。

app.rbを下記のように変更します。

require 'sinatra'
require 'sinatra/reloader'

get '/' do
  'how are you?'
end

get '/path/to' do
  "this is [/path/to]"
end

get '/hello/*' do |name|
  "hello #{name}. how are you?"
end

get '/erb_template_page' do
  erb :erb_template_page
end

# ここから
get '/markdown_template_page' do
  markdown :markdown_template_page
end
# ここまでを追加

さらにファイルを追加します。

touch views/markdown_template_page.markdown

上記Markdownファイルに下記のように追記します。

# this is markdown_template_page!

ブラウザでアクセス
http://localhost:4567/markdown_template_page

MarkdownがHTMLにレンダリングされて表示されます。
単純に静的ページをサクッと作りたい場合はerbよりも簡単かと思います。

erbとmarkdownを組み合わせてみる

app.rbを下記のように変更します。

require 'sinatra'
require 'sinatra/reloader'

get '/' do
  'how are you?'
end

get '/path/to' do
  "this is [/path/to]"
end

get '/hello/*' do |name|
  "hello #{name}. how are you?"
end

get '/erb_template_page' do
  erb :erb_template_pae
end

get '/markdown_template_page' do
  markdown :markdown_template_pae
end

# ここから
get '/erb_and_md_template_page' do
  erb :erb_and_md_template_page, locals => { md => markdown(:erb_and_md_template_page) }
end
# ここまでを追加

erbファイルを作成
touch erb_and_md_template_page .erb

<%= Time.now %>>
<%= md %>

markdownファイルを作成
touch erb_and_md_template_page.md

# this is erb_and_md.md

ブラウザでアクセス
http://localhost:4567/erb_and_md_template_page

現在時刻と「this is erb_and_md.md」が表示されていればOKです。
もしくは、erbの中で直接#markdownメソッドを実行する方法もあります。

<%= Time.now %>
<%= markdown(:erb_and_md_template_page) %>

この辺を組み合わせると、markdownの場合にlayout.erbを適用するなどができるようになります。

レイアウトの適用

たとえば常に同じ内容を表示するヘッダーやフッターについて
あとで書く

参考資料

始めよう - Sinatra

  • 公式ドキュメントの日本語訳。部分的に情報が古いままのこともある。
  • が、基本的には翻訳されているので、読んでおくことをおすすめします。

sinatra/README.ja.md at master · sinatra/sinatra

  • 上記「始めよう - Sinatra」のGitHubにある元ファイル
  • 比較的最近にメンテナンスが入っているのでこちらも見るほうがいいかも

入門 Sinatra――Web制作のためのシンプルなRuby DSL

  • 電子書籍

ほか、おすすめあれば教えていただけると幸いです。