Sinatra 入門

Rubyを使ったウェブサービスの作成はRuby on Railsが有名らしい
調べたところRailsは機能フル装備で中上級者用とあったので軽量のSinatraというパッケージを利用する。
>参考: [たった5行のコードでWebサービス！Sinatra, Rubyとは？](https://it.typeac.jp/article/show/5)
>引用: [Sinatra入門 (全17回) - ドットインストール](http://dotinstall.com/lessons/basic_sinatra)
 
 
#01 Sinatraとはなにか？
```bash
Mac-no-MacBook-Pro:~ Mac$ gem install sinatra
```
待機なげえ

```bash
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`

```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[シンボル、：変数]}`

```rb
get "/hello/:name" do
  "hello #{prams[:name]}”
end
```
 
`params=` パラメーターズの意味
 
`params[]`をいちいち書くのが面倒な時は

```rb
get "/hello/:name" do |n|
  "hello #{n}"
end
```
 
ブロックを使えばいい
 
またパラメーターは２つ以上設定でき`|f,l|`のようにする
 
またパラメーターをオプションにしたい時は

```rb
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では

```rb:main.rb
get "/" do
  erb :index
end
```
index.erbでは

```rb: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部分に該当するのを書く

```ruby: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

```

```erb:layout.erb
<!DOCTYPE html>
<html lang="ja">
<head>
  <mata charset="utf-8">
  <title><%= title %></title>
</head>
<body>
	<%= yield %>
</body>
</html>
```

```erb:index.erb
<div><%= @content %></div>
```

```erb:about.erb
<div><%= @content %></div>
<div><%= @email %></div>
```



#09 before/afterフィルタを使おう
**レイアウトにたよらない方法!**

```ruby: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や各レイアウトでよく使う処理を登録
共通関数の定義でいろいろなところから使う

```rb
helpers do
	
end
```
のなかに関数の定義を追加する。
実例↓

```ruby: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の勉強必要

下準備

```ruby:sinatra_lessons>main.rb
require "sinatra"
require "sinatra/reloader"

get "/" do 
	erb :index
end
```

```erb:sinatra_lessons>index.erb
<!DOCTYPE html>
<html lang="ja">
<head>
	<mata charset="utf-8">
	<title><%= @title%></title>
</head>
<body>
	<div> <%= @content %></div>
</body>
</html>
```

```sql:import.sql
create table comments(
	id integer primary key,
	body text
);

```


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

```bash
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変数にデータベースの中身を入れる

```ruby: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 コメントの一覧を表示させよう
変数の中身を表示する場合`<%= %>`
制御文の場合`<% %>`

```erb: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コメントを投稿
データベースにデータがないので投稿するためのフォームを作る

```erb: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>
```
フォームに何かを入れると登録されるようにする

```ruby: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機能を使い、コメントを削除できるようにしていきます。

```erb: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コメントを削除してみよう２
データベースからコメントを削除する機能を実現する

```ruby: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　エスケープ処理
悪意のあるコードを入力された時にエスケープする

```ruby:main.rb
helpers do
	include Rack::Utils
	alias_method :h,:escape_html
end
```

```erb: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>
```