Edited at

Sinatra 入門

More than 3 years have passed since last update.

Rubyを使ったウェブサービスの作成はRuby on Railsが有名らしい

調べたところRailsは機能フル装備で中上級者用とあったので軽量のSinatraというパッケージを利用する。


参考: たった5行のコードでWebサービス!Sinatra, Rubyとは?

引用: Sinatra入門 (全17回) - ドットインストール



01 Sinatraとはなにか?

Mac-no-MacBook-Pro:~ Mac$ gem install sinatra

待機なげえ

Fetching: rack-1.6.0.gem (100%)

Successfully installed rack-1.6.0
Fetching: tilt-1.4.1.gem (100%)
Successfully installed tilt-1.4.1
Fetching: rack-protection-1.5.3.gem (100%)
Successfully installed rack-protection-1.5.3
Fetching: sinatra-1.4.5.gem (100%)
Successfully installed sinatra-1.4.5
Parsing documentation for rack-1.6.0
Installing ri documentation for rack-1.6.0
Parsing documentation for rack-protection-1.5.3
Installing ri documentation for rack-protection-1.5.3
Parsing documentation for sinatra-1.4.5
Installing ri documentation for sinatra-1.4.5
Parsing documentation for tilt-1.4.1
Installing ri documentation for tilt-1.4.1
Done installing documentation for rack, rack-protection, sinatra, tilt after 211 seconds
4 gems installed

Mac-no-MacBook-Pro:~ Mac$ gem install sqlite3
Building native extensions. This could take a while...
Successfully installed sqlite3-1.3.10
Parsing documentation for sqlite3-1.3.10
Done installing documentation for sqlite3 after 0 seconds
1 gem installed

Mac-no-MacBook-Pro:~ Mac$ gem install sinatra-contrib
Fetching: backports-3.6.4.gem (100%)
Successfully installed backports-3.6.4
Fetching: rack-test-0.6.3.gem (100%)
Successfully installed rack-test-0.6.3
Fetching: multi_json-1.10.1.gem (100%)
Successfully installed multi_json-1.10.1
Fetching: sinatra-contrib-1.4.2.gem (100%)
Successfully installed sinatra-contrib-1.4.2
Parsing documentation for backports-3.6.4
Installing ri documentation for backports-3.6.4
Parsing documentation for multi_json-1.10.1
Installing ri documentation for multi_json-1.10.1
Parsing documentation for rack-test-0.6.3
Installing ri documentation for rack-test-0.6.3
Parsing documentation for sinatra-contrib-1.4.2
Installing ri documentation for sinatra-contrib-1.4.2
Done installing documentation for backports, multi_json, rack-test, sinatra-contrib after 2 seconds
4 gems installed

Mac-no-MacBook-Pro:~ Mac$ gem install activerecord
Fetching: thread_safe-0.3.4.gem (100%)
Successfully installed thread_safe-0.3.4
Fetching: minitest-5.5.1.gem (100%)
Successfully installed minitest-5.5.1
Fetching: tzinfo-1.2.2.gem (100%)
Successfully installed tzinfo-1.2.2
Fetching: i18n-0.7.0.gem (100%)
Successfully installed i18n-0.7.0
Fetching: activesupport-4.2.0.gem (100%)
Successfully installed activesupport-4.2.0
Fetching: builder-3.2.2.gem (100%)
Successfully installed builder-3.2.2
Fetching: activemodel-4.2.0.gem (100%)
Successfully installed activemodel-4.2.0
Fetching: arel-6.0.0.gem (100%)
Successfully installed arel-6.0.0
Fetching: activerecord-4.2.0.gem (100%)
Successfully installed activerecord-4.2.0
Parsing documentation for activemodel-4.2.0
Installing ri documentation for activemodel-4.2.0
Parsing documentation for activerecord-4.2.0
Installing ri documentation for activerecord-4.2.0
Parsing documentation for activesupport-4.2.0
Installing ri documentation for activesupport-4.2.0
Parsing documentation for arel-6.0.0
Installing ri documentation for arel-6.0.0
Parsing documentation for builder-3.2.2
Installing ri documentation for builder-3.2.2
Parsing documentation for i18n-0.7.0
Installing ri documentation for i18n-0.7.0
Parsing documentation for minitest-5.5.1
Installing ri documentation for minitest-5.5.1
Parsing documentation for thread_safe-0.3.4
Installing ri documentation for thread_safe-0.3.4
Parsing documentation for tzinfo-1.2.2
Installing ri documentation for tzinfo-1.2.2
Done installing documentation for activemodel, activerecord, activesupport, arel, builder, i18n, minitest, thread_safe, tzinfo after 16 seconds
9 gems installed


02 はじめてのSinatra

ターミナルでruby main.rb

Mac-no-MacBook-Pro:sinatora_lessons Mac$ ruby main.rb

[2015-01-31 00:57:53] INFO WEBrick 1.3.1
[2015-01-31 00:57:53] INFO ruby 2.1.2 (2014-05-08) [x86_64-darwin14.0]
== Sinatra/1.4.5 has taken the stage on 4567 for development with backup from WEBrick
[2015-01-31 00:57:53] INFO WEBrick::HTTPServer#start: pid=62144 port=4567
127.0.0.1 - - [31/Jan/2015:00:58:19 +0900] "GET / HTTP/1.1" 200 11 0.0091
localhost - - [31/Jan/2015:00:58:19 JST] "GET / HTTP/1.1" 200 11
- -> /
127.0.0.1 - - [31/
Jan/2015:00:58:20 +0900] "GET /favicon.ico HTTP/1.1" 404 448 0.0009
localhost - - [31/Jan/2015:00:58:20 JST] "GET /favicon.ico HTTP/1.1" 404 448
http://127.0.0.1:4567/ -> /favicon.ico


03 複数のリクエストに対応してみよう

いちいちwebrickを再起動するのはめんどくさいから

require “sinatra/reloader”

これはgem install sinatra-contribのおかげ


04 URLからのパラメータを使おう (1)

URLから渡されたパラメータ :name

コロンの後に変数をつけてシンボルにする

それを使うには、文字列の中で変数を展開するには、#{params[シンボル、:変数]}

get "/hello/:name" do

"hello #{prams[:name]}
end

params= パラメーターズの意味

params[]をいちいち書くのが面倒な時は

get "/hello/:name" do |n|

"hello #{n}"
end

ブロックを使えばいい

またパラメーターは2つ以上設定でき|f,l|のようにする

またパラメーターをオプションにしたい時は

get "/hello/:fname/?:lname?” do |f,l|

"
hello #{f} #{l}"
end

シンボル?のようにする


05 URLからのパラメータを使おう (2)

ワイルドカード *何でも

正規表現%r{}

[0-9]* 数字、0-9の繰り返し

正規表現にマッチした場合表示される


06 ERBテンプレートを使おう

viewsのフォルダを作る

その下にindex.erb

main.rbでは


main.rb

get "/" do

erb :index
end

index.erbでは


index.erb

<!DOCTYPE html>

<html lang="ja">
<head>
<mata charset="utf-8">
<title>sinatra</title>
</
head>
<body>
<h1>heloo</h1>
</
body>
</html>


07 テンプレートで変数を使ってみよう

受け取ったパラメーターをテンプレート(views)に反映させる(index.erb)には@nameなどに代入する

テンプレートに変数の値を表示させたい場合、@がついた変数名を<%= %>で囲む

=>@がついた変数名はテンプレートで使える


08 layout.erbを使ってみよう

テンプレートが多くなった時にviewsフォルダにlayout.erbを作る

共通部分以外を<%= yield%>にする

*layout.erbにはviews各ファイルで共通する部分を入れる。

*viewsの各レイアウト(index.erbやabout.erb)にはlayout.erbのyield部分に該当するのを書く


main.rb

require = 'sinatra'

require = 'sinatra/reloader'

get "/" do
@title = "main"
@content = "main contnt"
erb :index
end

get "/about" do
@title = "about"
@content = "about contnt"
@email = 'mail@k.com'
erb :about
end



layout.erb

<!DOCTYPE html>

<html lang="ja">
<head>
<mata charset="utf-8">
<title><%= title %></title>
</head>
<body>
<%= yield %>
</body>
</html>


index.erb

<div><%= @content %></div>



about.erb

<div><%= @content %></div>

<div><%= @email %></div>


09 before/afterフィルタを使おう

レイアウトにたよらない方法!


main.rb

require = 'sinatra'

require = 'sinatra/reloader'

1.before do
@author = "kimioka"
end

2.before '/admin/*' do
@msg = "admin area"
end

3.after do
logger.info "page displayed"
end

get "/" do
@title = "main"
@content = "main contnt" + @author
erb :index
end

get "/about" do
@title = "about"
@content = "about contnt"+ @author
@email = 'mail@k.com'
erb :about
end



10 helperを使ってみよう

main.rbや各レイアウトでよく使う処理を登録

共通関数の定義でいろいろなところから使う

helpers do

end

のなかに関数の定義を追加する。

実例↓


main.rb

require = 'sinatra'

require = 'sinatra/reloader'

before do
@author = "kimioka"
end
helpers do
def strong(a)
<strong> #{a} </strong>
end
end

get "/" do
@title = "main"
@content = "main contnt" + strong(@author)
erb :index
end



11 掲示板アプリを作ってみよう

データベースの設定

sqlの勉強必要

下準備


sinatra_lessons>main.rb

require "sinatra"

require "sinatra/reloader"

get "/" do
erb :index
end



sinatra_lessons>index.erb

<!DOCTYPE html>

<html lang="ja">
<head>
<mata charset="utf-8">
<title><%= @title%></title>
</head>
<body>
<div> <%= @content %></div>
</body>
</html>


import.sql

create table comments(

id integer primary key,
body text
);


bbs.dbを作成、import.sqlの読み込み

sinatora_lessons Mac$ sqlite3 bbs.db

SQLite version 3.8.5 2014-08-15 22:37:57
Enter ".help" for usage hints.
sqlite> .read import.sql
sqlite> .schema
CREATE TABLE comments(
id integer primary key,
body text
);
sqlite> select * from comments;


12 ActiveRecordを使ってみよう

データベースの設定ができたのでActiveRecordを使って読み出す


active_recordってなに


@comments変数にデータベースの中身を入れる


sinatra_lessons>main.rb

require "sinatra"

require "sinatra/reloader"
require 'active_record'

ActiveRecord::Base.establish_connection(
"adapter" => "sqlite3",
"database" => "./bbs.db"
)

class Comment < ActiveRecord::Base
end

get "/" do
@comments = Comment.order("id desc").all
erb :index
end



13 コメントの一覧を表示させよう

変数の中身を表示する場合<%= %>

制御文の場合<% %>


sinatra_lessons>index.erb

<!DOCTYPE html>

<html lang="ja">
<head>
<mata charset="utf-8">
<title>BBS</title>
</head>
<body>
<h1>BBS</h1>
<ul>
<% @comments.each do |comment| %>
<li data-id= "<%= comment.id %>">
<%= comment.body %>
</li>
<% end %>
</ul>
</body>
</html>


14コメントを投稿

データベースにデータがないので投稿するためのフォームを作る


sinatra_lessons>index.erb

<!DOCTYPE html>

<html lang="ja">
<head>
<mata charset="utf-8">
<title>BBS</title>
</head>
<body>
<h1>BBS</h1>
<ul>
<% @comments.each do |comment| %>
<li data-id= "<%= comment.id %>">
<%= comment.body %>
</li>
<% end %>
</ul>
<h2>Add new</h2>
<form method="post" action="/new">
<input type= "text" name="body"><input type= "submit" value="post!">
</form>
</body>
</html>

フォームに何かを入れると登録されるようにする


main.rb

require "sinatra"

require "sinatra/reloader"
require 'active_record'

ActiveRecord::Base.establish_connection(
"adapter" => "sqlite3",
"database" => "./bbs.db"
)

class Comment < ActiveRecord::Base
end

get "/" do
@comments = Comment.order("id desc").all
erb :index
end

post "/new" do
Comment.create({:body => params[:body]})
redirect '/'
erb :index
end



15 コメントを削除してみよう (1)

jQueryのAjax機能を使い、コメントを削除できるようにしていきます。


sinatra_lessons>index.erb

<!DOCTYPE html>

<html lang="ja">
<head>
<mata charset="utf-8">
<title>BBS</title>
</head>
<body>
<h1>BBS</h1>
<ul>
<% @comments.each do |comment| %>
<li data-id= "<%= comment.id %>">
<%= comment.body %>
</li>
<% end %>
</ul>
<h2>Add new</h2>
<form method="post" action="/new">
<input type= "text" name="body"><input type= "submit" value="post!">
</form>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script>
$('.deleteCmd').click(function(){
var el = $(this).parent();
if (confirm('are you sure to delete?')){
$.post('/delete',{
id: el.data('id')
},function(){
el.fadeOut(800);
});
}
})
</script>
</body>
</html>


16コメントを削除してみよう2

データベースからコメントを削除する機能を実現する


main.rb

require "sinatra"

require "sinatra/reloader"
require 'active_record'

ActiveRecord::Base.establish_connection(
"adapter" => "sqlite3",
"database" => "./bbs.db"
)

class Comment < ActiveRecord::Base
end

get "/" do
@comments = Comment.order("id desc").all
erb :index
end

post "/new" do
Comment.create({:body => params[:body]})
redirect '/'
erb :index
end

post'/delete' do
Comment.find(params[:id]).destroy
end



17 エスケープ処理

悪意のあるコードを入力された時にエスケープする


main.rb

helpers do

include Rack::Utils
alias_method :h,:escape_html
end


sinatra_lessons>index.erb

<!DOCTYPE html>

<html lang="ja">
<head>
<mata charset="utf-8">
<title>BBS</title>
</head>
<body>
<h1>BBS</h1>
<ul>
<% @comments.each do |comment| %>
<li data-id= "<%= comment.id %>">
>>> <%= h comment.body %>
</li>
<% end %>
</ul>
<h2>Add new</h2>
<form method="post" action="/new">
<input type= "text" name="body"><input type= "submit" value="post!">
</form>

</body>
</html>