sinatraで一からwebアプリケーションを構築する

# 背景
ある程度中規模のアプリケーションを作成する前提で、[公式サイトの「Getting Started」](http://www.sinatrarb.com/intro-jp.html)とは構成を変える。Viewは別ファイルへ分ける。Modelはクラスを分ける。サーバー実行コードをアプリケーションコードから分ける。ライブラリはbundlerで管理する。Viewはhaml, sass, coffeescriptを使用する。テストにはrspecを使用する。

# 実装
## ディレクトリ作成
```
$ mkdir app
$ cd app/
```

## bundlerの準備
### Gemfileの作成とインストール先のDir作成
```
$ bundle init
$ mkdir -p vender/bundle
$ vim Gemfile
```
### 必要なライブラリを書く
jsにはcoffee-script, cssにはsass, htmlテンプレートにはhamlを使用する。
開発環境での実行にはshotgunを使用する。
テストフレームワークにはrspecを使用する。

```ruby:Gemfile
source "https://rubygems.org"

gem 'sinatra'
gem "sass"
gem "haml"
gem "coffee-script"
gem "shotgun"

group :test do
  gem 'rspec'
end
```

### ライブラリのインストール
インストール先にvender/bundleを指定する。

```
$ bundle install --path vender/bundle
```

## アプリケーションを構成
1. ルーティングを行うためのapp.rbを作成する。
2. アプリケーション起動のためのconfig.ruを作成する
3. sass, coffee-scriptのファイルを置いておくためのassets/を作成する
4. hamlを置いておくためのviews/を作成する
5. modelファイルを置いておくためのmodels/を作成する
6. modelをロードするためのinit.rbを作成する。
7. テストを置いておくためのspec/を作成する

```
$ touch app.rb
$ touch config.ru
$ mkdir -p assets/js assets/css
$ mkdir views
$ touch views/index.haml
$ mkdir models
$ touch models/init.rb
$ mkdir spec
```

### ルーティングを行う
ルーティングとコントローラをまとめて書く

```ruby:app.rb
require 'sinatra/base'
require 'haml'
require 'sass'
require 'coffee-script'

require_relative 'models/init'

class Server < Sinatra::Base
  get '/' do
    haml :index
  end 
end
```

### サーバー設定を行う
サーバーの設定を別ファイルへ分ける。

```ruby:config.ru
root = ::File.dirname(__FILE__)
require ::File.join(root, 'app')

run Server
```

### Viewを作成する
```haml:index.haml
%h1 This is the application root.
```

### アプリケーションを実行してみる
development環境でアプリケーションを実行する。

```
$ bundle exec shotgun
```

## Modelを作成する

1. Rakefileを作成して、テストの実行環境を整える
1. Specファイルを作成しテストを書く 
2. Modelのクラスを作成する
3. テストが意図したとおり通らないことを確認する
4. Modelへテストを通すために必要なコードを追加する
5. テストが意図したとおり通ることを確認する

### テストの実行環境を整える
コマンドで全てのテストファイルが一括実行されるようにする。

```
$ touch Rakefile
```
```ruby:Rakefile
require 'rspec/core/rake_task'
desc "run spec"
task :default => [:spec]

RSpec::Core::RakeTask.new(:spec) do |spec|
  spec.pattern = 'spec/*_spec.rb'
  spec.rspec_opts = %w(--color --format progress)
end
```

RSpecの設定を行う。全てのspecファイルでこのspec_helperをロードする。

```
$ touch spec/spec_helper.rb
```
```ruby:spec/spec_helper.rb
ENV['RACK_ENV'] = 'test'

require File.join(File.dirname(__FILE__), '..', 'app.rb')

require 'rspec'
require 'rack/test'

set :environment, :test
set :run, false
set :raise_errors, true
set :logging, false


RSpec.configure do |conf|
  conf.include Rack::Test::Methods
end

def app 
  Sinatra::Application
end
```

### Specファイルを作成する
models/以下に***_spec.rbのパターンで、モデルのテストを作成する。

```spec/models/hoge_spec.rb
require 'spec_helper'

describe Hoge do
  it "should print String" do
    expect(Hoge.new.puts).to be_instance_of String
  end 
end
```
###  Modelクラスを作成する

まずはテストが通らないことを確認するためになにも書かない。

```ruby:models/hoge.rb
class Hoge
end
```

### アプリケーションに読み込ませる
```ruby:models/init.rb
require_relative 'hoge'
```

### テストを行う
テストが通らないことを確認する。

```
$ bundle exec rake spec
```
### Modelクラスを編集する
テストが通るように編集する。

```ruby:models/hoge.rb
class Hoge
  def puts
    'Hello'
  end
end
```
### テストを行う
テストが通ることを確認する。

```
$ bundle exec rake spec
```

あとはapp.rbの中で作成したmodelを利用する。

# 参考資料
※ あとで