Webアプリモックアップ環境構築(Sinatra, Guard, Slim, TwitterBootstrap)

[Webアプリのモックアップ作業土台を作る その1 - cu39's diary](http://cu39.hateblo.jp/entry/2013/07/02/183935)

上記を参考に、画面遷移を重視したモックアップを高速に構築できる環境を揃えてみました

このセットアップを終えれば、下記のような画面を用意することができます

![Screenshot from 2014-09-13 12:45:41.png](https://qiita-image-store.s3.amazonaws.com/0/22754/2909f93f-3dfb-7ea2-6e7b-d17af69b28a0.png)

![Screenshot from 2014-09-13 12:37:02.png](https://qiita-image-store.s3.amazonaws.com/0/22754/23ee743d-8d10-b757-0255-ec9675b3196e.png)

概要:
-----

ターゲット環境: Ruby 2.1.2

* マークアップ: slim/sassとredcarpet(Markdown)
* デザインフレームワーク: sinatra-twitter-bootstrap
* デバッグ: pry-byebugとpry-rescue
* ダミーデータ: Forgery
* 実行環境: bundler、thin、guard、livereload

これらで一通りのことは可能となります

DBはスコープ外としました

### [参考WEB](http://cu39.hateblo.jp/entry/2013/07/02/183935)との違い: ###

1. shotgun(thin)の起動をforemanからguardにしている  
   → foreman起動だと、binding.pry時のPryコンソール操作ができない模様
2. coffee-script等Javascript関連のフレームワークを入れていない  
   → インタラクションはスコープ外とした

### ポイント ###

1. sinatra-twitter-bootstrapが提供するHelperはhaml向けとなっていますが、CSSやJavascriptのロードはしてくるため、sassでもclassを指定すれば問題なく使えます
2. Markdownは、ドキュメント等を貼り付ける際に利用します


環境構築:
---------

### 構成 ###

```
├── Gemfile
├── Guardfile
├── config.ru
├── webapp.rb
└── views/
    ├── application.sass
    ├── layout_1col.slim
    ├── index.slim
    ├── layout.slim
    └── dashboard.slim
```

### ファイル ###

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

gem "sinatra", require: "sinatra/base"
gem "sinatra-contrib", require: "sinatra/reloader"

gem "slim"
gem "redcarpet"
gem "sass"
gem "sinatra-twitter-bootstrap" # need `require "sinatra/twitter-bootstrap"` in config.ru

group :development do
  if RUBY_VERSION >= '2.0.0'
    gem "pry-byebug"
  else
    gem "pry-debugger"
  end
  gem "pry-rescue"
  gem "pry-stack_explorer"
  gem "tapp"

  gem "rspec"

  gem "thin", require: false
  gem "guard", "~> 2.0", require: false
  gem "guard-shotgun"
  gem "rack-livereload"
  gem "guard-livereload", require: false

  gem "forgery"
end
```

```rb:Guardfile 
guard 'livereload' do
  watch(%r{views/.+\.(slim|sass)$})
  watch("webapp.rb")
  watch("config.ru")
end

guard :shotgun, server: "thin", host: "0.0.0.0", port: "3000" do
end
```

```config.ru 
require 'bundler'
Bundler.require(:default, ENV['RACK_ENV'].to_sym)
require "sinatra/twitter-bootstrap"
begin
  use Rack::LiveReload, no_swf: true
rescue
  nil
end

require File.expand_path(File.join('..','webapp'), __FILE__)
run WebApp
```

```webapp.rb
class WebApp < Sinatra::Base
  register Sinatra::Twitter::Bootstrap::Assets
  configure :development do
    register Sinatra::Reloader
  end
  enable :sessions

  get "/css/application.css" do
    sass :application
  end

  get "/" do
    @title = "Welcome"
    slim :index, :layout => :layout_1col
  end

  get "/dashboard" do
    @title = "Dashboard"
    # generate random data for demo.
    @list = (1..8).map do |i|
      {
        id: i,
        name: Forgery(:name).full_name,
        email: Forgery(:internet).email_address,
        joined: Forgery(:date).date.to_time
      }
    end
    slim :dashboard
  end
end
```

```views/application.sass
body
  background-color: #fff
```

```views/layout_1col.slim
doctype html
html
  head
    title = @title
    == bootstrap_assets
    link href="/css/application.css" rel="stylesheet"
  body
    .container-fluid
      == yield
```

```views/index.slim
.row-fluid
  .span12
    .hero-unit
      h1 Welcome!
      p This is WebApp high-speed mock up.
      a.btn.btn-large[href="dashboard"] Dashboard
.row-fluid
  .span12
    markdown:
      ----

      Document
      ========

      Reference: [Webアプリモックアップ環境構築(Sinatra, Guard, Slim, TwitterBootstrap)](http://qiita.com/ma2shita/items/e9c6d399f9597e3991e6)
```

```views/layout.slim
doctype html
html
  head
    title = @title
    == bootstrap_assets
    link href="/css/application.css" rel="stylesheet"
  body
    .container-fluid
      .row-fluid
        .span12
          h2 Header
      .row-fluid
        .span2
          ul.nav.nav-list
            li: a[href="/"] Home
            li.nav-header Users
            li: a Summary
            li
              a
                = "List "
                span.badge 8
            li.divider
            li: a[href="/"] Logout
        .span10
          == yield
      .row-fluid
        .span12
          p Footer
```

```views/dashboard.slim
.row-fluid
  .span12
    h1 Dashboard
    table.table.table-bordered.table-striped
      tr
        th ID
        th Name
        th Email
        th Join date
      - for e in @list
        tr
          td = e[:id]
          td = e[:name]
          td = e[:email]
          td = e[:joined].to_s
```

### 実行 ###

```
$ bundle install --path .bundle/gems --jobs 4
$ bundle exec guard -i
==> Ctrl+C STOP
```

open http://localhost:3000



### ポイント ###

guardの引数`-i`を付け忘れると、binding.pry時のPryコンソールの反応が鈍かったりと、不都合が発生します (おそらく入力をguardとPryコンソールで取り合ってる可能性があり)

guardのバージョンが1.x系だと、guardが下記エラーを出して起動できません。2.x系を使用するようにしましょう

```
guard.rb:133: in `setup_listener': undefined method `change' for #<Listen::Listener > ...
```

~~guard-shotgunの本家バージョンには、プロセスspawnに問題があり、guardは起動できるがshotgunが起動できないという問題があります。2014年9月上旬段階では、[拙作のbranch](https://github.com/ma2shita/guard-shotgun/tree/spawnIssueSpike)を使うようにしています~~

→ [PRがマージされました](https://github.com/rchampourlier/guard-shotgun/pull/8)

config.ruで`require "sinatra/twitter-bootstrap"`としていますが、Bundler.requireで読み込まれないのはなぜだろう？


参考資料
--------

* [Webアプリのモックアップ作業土台を作る その1 - cu39's diary](http://cu39.hateblo.jp/entry/2013/07/02/183935)

* [Sinatra: README (Japanese)](http://www.sinatrarb.com/intro-ja.html)
* [Getting · Bootstrap](http://getbootstrap.com/2.3.2/getting-started.html)
* [slim/README.jp.md at master · slim-template/slim](https://github.com/slim-template/slim/blob/master/README.jp.md)
* [sevenwire/forgery](https://github.com/sevenwire/forgery)

* [guard.rb:133: in `setup\_listener': undefined method `change' for #<Listen::Listener > ... · Issue #90 · guard/guard-livereload](https://github.com/guard/guard-livereload/issues/90)
* [Ruby - Gemfileでのgem指定色々 - Qiita](http://qiita.com/yaotti/items/510779877e515a1155db) 
* [Windows - ディレクトリ構成図を書くときに便利な記号 - Qiita](http://qiita.com/paty-fakename/items/c82ed27b4070feeceff6)


あとがき
-------

このへんはやっておきたい

1. DB環境  
   → 具体的にはSequel。ストレージにBerkeley DB使えるといいかもしれない(ローカルなKVSでコンパクト&スキーマレス)
2. sinatra-twitter-bootstrap  
   → Bundler.requre対応、3.0系&バージョニング対応、slim向けHelper(これはどうでもいいかな？)
3. annotatorjs
   → 意見をもらうためのアノテーションの仕組みが必要かな

さよなら、さよなら。さよなら。