あとでもっかい試す用 - Ruby on Rails 4.0 チュートリアル - 第五章


[Ruby on Rails チュートリアル 実例を使ってRailsを学ぼう 第5章](http://railstutorial.jp/chapters/filling-in-the-layout?version=4.0#top)を見ながらやったことを、あとでもう一度できるようにまとめます！！第五章！！

- Bootstrap
- パーシャル
- Railsのルーティング
- Asset Pipeline
- Sass
- RSpecリファクタリング

# 準備

	$ git checkout -b filling-in-layout

# ナビゲーションをつける


レイアウトファイルを修正

````
$ subl app/views/layouts/application.html.erb
	
<!DOCTYPE html>
<html>
  <head>
    <title><%= full_title(yield(:title)) %></title>
    <%= stylesheet_link_tag "application", media: "all",
                                           "data-turbolinks-track" => true %>
    <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
    <%= csrf_meta_tags %>
    <!--[if lt IE 9]>
    <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->
  </head>
  <body>
    <header class="navbar navbar-fixed-top navbar-inverse">
      <div class="navbar-inner">
        <div class="container">
          <%= link_to "sample app", '#', id: "logo" %>
          <nav>
            <ul class="nav pull-right">
              <li><%= link_to "Home",    '#' %></li>
              <li><%= link_to "Help",    '#' %></li>
              <li><%= link_to "Sign in", '#' %></li>
            </ul>
          </nav>
        </div>
      </div>
    </header>
    <div class="container">
      <%= yield %>
    </div>
  </body>
</html>
````

Homeページを修正

	<div class="center hero-unit">
	  <h1>Welcome to the Sample App</h1>
	
	  <h2>
	    This is the home page for the
	    <a href="http://railstutorial.jp/">Ruby on Rails Tutorial</a>
	    sample application.
	  </h2>
	
	  <%= link_to "Sign up now!", '#', class: "btn btn-large btn-primary" %>
	</div>
	
	<%= link_to image_tag("rails.png", alt: "Rails"), 'http://rubyonrails.org/' %>

画像をダウンロード

	$ cd app/assets/images/
	$ wget http://rubyonrails.org/images/rails.png
	$ cd ../../..

# bootstrapとカスタムCSS

Gemfileにbootstrap-sassを追加する。

	$ subl Gemfile

	 gem 'rails', '4.0.0'
	+gem 'bootstrap-sass', '2.3.2.0'
	 	
	 group :development, :test do
	 gem 'sqlite3', '1.3.7'

bundle インストール

	$ bundle install

Asset Pipelineと互換性を持つ為の設定をする。

	$ subl config/application.rb
	
	     # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
	     # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.	{rb,yml}').to_s]
	     # config.i18n.default_locale = :de
	+
	+    config.assets.precompile += %w(*.png *.jpg *.jpeg *.gif)
	   end
	 end 
カスタムCSSを追加する為のファイルを作成する

	$ touch app/assets/stylesheets/custom.css.scss
	$ subl app/assets/stylesheets/custom.css.scss

	+ @import "bootstrap";

さらにカスタムCSSを修正

````
$ subl app/assets/stylesheets/custom.css.scss

@import "bootstrap";

/* universal */

html {
  overflow-y: scroll;
}

body {
  padding-top: 60px;
}

section {
  overflow: auto;
}

textarea {
  resize: vertical;
}

.center {
  text-align: center;
}

.center h1 {
  margin-bottom: 10px;
}


/* typography */

h1, h2, h3, h4, h5, h6 {
  line-height: 1;
}

h1 {
  font-size: 3em;
  letter-spacing: -2px;
  margin-bottom: 30px;
  text-align: center;
}

h2 {
  font-size: 1.2em;
  letter-spacing: -1px;
  margin-bottom: 30px;
  text-align: center;
  font-weight: normal;
  color: #999;
}

p {
  font-size: 1.1em;
  line-height: 1.7em;
}

/* header */

#logo {
  float: left;
  margin-right: 10px;
  font-size: 1.7em;
  color: #fff;
  text-transform: uppercase;
  letter-spacing: -1px;
  padding-top: 9px;
  font-weight: bold;
  line-height: 1;
}

#logo:hover {
  color: #fff;
  text-decoration: none;
}
````

# パーシャル (partial)

レイアウトファイルの内容を別ファイルに分ける。

	$ subl app/views/layouts/_shim.html.erb
	
	<!--[if lt IE 9]>
	<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
	<![endif]-->

ヘッダーをパーシャルで定義。

	$ subl app/views/layouts/_header.html.erb

	<header class="navbar navbar-fixed-top navbar-inverse">
	  <div class="navbar-inner">
	    <div class="container">
	      <%= link_to "sample app", '#', id: "logo" %>
	      <nav>
	        <ul class="nav pull-right">
	          <li><%= link_to "Home",    '#' %></li>
	          <li><%= link_to "Help",    '#' %></li>
	          <li><%= link_to "Sign in", '#' %></li>
	        </ul>
	      </nav>
	    </div>
	  </div>
	</header>

フッターも。

	$ subl app/views/layouts/_footer.html.erb

	<footer class="footer">
	  <small>
	    <a href="http://railstutorial.jp/">Rails Tutorial</a>
	    by Michael Hartl
	  </small>
	  <nav>
	    <ul>
	      <li><%= link_to "About",   '#' %></li>
	      <li><%= link_to "Contact", '#' %></li>
	      <li><a href="http://news.railstutorial.jp/">News</a></li>
	    </ul>
	  </nav>
	</footer>

レイアウトファイルにパーシャルを適用

	$ subl app/views/layouts/application.html.erb

	<!DOCTYPE html>
	<html>
	  <head>
	    <title><%= full_title(yield(:title)) %></title>
	    <%= stylesheet_link_tag "application", media: "all",
	                                           "data-turbolinks-track" => true %>
	    <%= javascript_include_tag "application", "data-turbolinks-track" => 	true %>
	    <%= csrf_meta_tags %>
	    <%= render 'layouts/shim' %>
	  </head>
	  <body>
	    <%= render 'layouts/header' %>
	    <div class="container">
	      <%= yield %>
	      <%= render 'layouts/footer' %>
	    </div>
	  </body>
	</html>

フッターの見た目を良くする。CSS修正。

	$subl app/assets/stylesheets/custom.css.scss

	/* footer */
	
	footer {
	  margin-top: 45px;
	  padding-top: 5px;
	  border-top: 1px solid #eaeaea;
	  color: #999;
	}
	
	footer a {
	  color: #555;
	}
	
	footer a:hover {
	  color: #222;
	}
	
	footer small {
	  float: left;
	}
	
	footer ul {
	  float: right;
	  list-style: none;
	}
	
	footer ul li {
	  float: left;
	  margin-left: 10px;
	}

# SassとAsset Pipeline

## アセットディレクトリ

- app/assets: 現在のアプリケーション固有のアセット
- lib/assets: あなたの開発チームによって作成されたライブラリ用のアセット
- vendor/assets: サードパーティのアセット

## マニフェストファイル

アセットファイルをどのように一つにするのかをRailsに伝える。

app/assets/stylesheets/application.css

## プリプロセッサエンジン

coffeeスクリプト, scss, erbをコンパイルするプロセッサ。

# SCSS

## ネスト

	.center {
	  text-align: center;
	}
	
	.center h1 {
	  margin-bottom: 10px;
	}

↑これを↓こうかける。

	.center {
	  text-align: center;
	  h1 {
	    margin-bottom: 10px;
	  }
	}

## 変数

	h2 {
	  .
	  .
	  .
	  color: #999;
	}
	.
	.
	.
	footer {
	  .
	  .
	  .
	  color: #999;
	}

↑これを↓こうかける。
	
	$lightGray: #999;
	.
	.
	.
	h2 {
	  .
	  .
	  .
	  color: $lightGray;
	}
	.
	.
	.
	footer {
	  .
	  .
	  .
	  color: $lightGray;
	}

## scssを使って書き換えたカスタムCSS

````
$ subl app/assets/stylesheets/custom.css.scss

@import "bootstrap";

/* mixins, variables, etc. */

$grayMediumLight: #eaeaea;

/* universal */

html {
  overflow-y: scroll;
}

body {
  padding-top: 60px;
}

section {
  overflow: auto;
}

textarea {
  resize: vertical;
}

.center {
  text-align: center;
  h1 {
    margin-bottom: 10px;
  }
}

/* typography */

h1, h2, h3, h4, h5, h6 {
  line-height: 1;
}

h1 {
  font-size: 3em;
  letter-spacing: -2px;
  margin-bottom: 30px;
  text-align: center;
}

h2 {
  font-size: 1.2em;
  letter-spacing: -1px;
  margin-bottom: 30px;
  text-align: center;
  font-weight: normal;
  color: $grayLight;
}

p {
  font-size: 1.1em;
  line-height: 1.7em;
}


/* header */

#logo {
  float: left;
  margin-right: 10px;
  font-size: 1.7em;
  color: white;
  text-transform: uppercase;
  letter-spacing: -1px;
  padding-top: 9px;
  font-weight: bold;
  line-height: 1;
  &:hover {
    color: white;
    text-decoration: none;
  }
}

/* footer */

footer {
  margin-top: 45px;
  padding-top: 5px;
  border-top: 1px solid $grayMediumLight;
  color: $grayLight;
  a {
    color: $gray;
    &:hover {
      color: $grayDarker;
    }
  }
  small {
    float: left;
  }
  ul {
    float: right;
    list-style: none;
    li {
      float: left;
      margin-left: 10px;
    }
  }
}
````


# Railsのルート

テストを名前付きルートを使ったものに修正する。

````
$ spec/requests/static_pages_spec.rb
	
require 'spec_helper'

describe "Static pages" do

  describe "Home page" do

    it "should have the h1 'Sample App'" do
      visit root_path
      expect(page).to have_content('Sample App')
    end

    it "should have the base title" do
      visit root_path
      expect(page).to have_title("Ruby on Rails Tutorial Sample App")
    end

    it "should not have a custom page title" do
      visit root_path
      expect(page).not_to have_title('| Home')
    end
  end

  describe "Help page" do

    it "should have the h1 'Help'" do
      visit help_path
      expect(page).to have_content('Help')
    end

    it "should have the title 'Help'" do
      visit help_path
      expect(page).to have_title("Ruby on Rails Tutorial Sample App | Help")
    end
  end

  describe "About page" do

    it "should have the h1 'About Us'" do
      visit about_path
      expect(page).to have_content('About Us')
    end

    it "should have the title 'About Us'" do
      visit about_path
      expect(page).to have_title("Ruby on Rails Tutorial Sample App | About Us")
    end
  end

  describe "Contact page" do

    it "should have the content 'Help'" do
      visit contact_path
      expect(page).to have_content('Contact')
    end

    it "should have the title 'Contact'" do
      visit contact_path
      expect(page).to have_title("Ruby on Rails Tutorial Sample App | Contact")
    end
  end
end
````

テストする

	$ bundle exec rspec spec/requests/static_pages_spec.rb
	=> 名前付きルートが定義されてないから失敗する。

ルートの定義を修正する。

	$ subl config/routes.rb
	
	 SampleApp::Application.routes.draw do
	-  get "static_pages/home"
	-  get "static_pages/help"
	-  get "static_pages/about"
	-  get "static_pages/contact"
	+  root  'static_pages#home'
	+  match '/help',    to: 'static_pages#help',    via: 'get'
	+  match '/about',   to: 'static_pages#about',   via: 'get'
	+  match '/contact', to: 'static_pages#contact', via: 'get'
	+  match '/about', to: 'static_pages#about',  via: 'get'

match '/about', to: 'static_pages#about',  via: 'get'
↑このコードは、↓この名前付きルートを生成する

	about_path -> '/about'
	about_url  -> 'http://localhost:3000/about'	

レイアウトファイルのリンクを修正

ヘッダ

	$ subl app/views/layouts/_header.html.erb 

	<header class="navbar navbar-fixed-top navbar-inverse">
	  <div class="navbar-inner">
	    <div class="container">
	      <%= link_to "sample app", root_path, id: "logo" %>
	      <nav>
	        <ul class="nav pull-right">
	          <li><%= link_to "Home",    root_path %></li>
	          <li><%= link_to "Help",    help_path %></li>
	          <li><%= link_to "Sign in", '#' %></li>
	        </ul>
	      </nav>
	    </div>
	  </div>
	</header>

フッタ

	$ subl touch app/views/layouts/_footer.html.erb

	<footer class="footer">
	  <small>
	    <a href="http://railstutorial.jp/">Rails Tutorial</a>
	    by Michael Hartl
	  </small>
	  <nav>
	    <ul>
	      <li><%= link_to "About",   about_path %></li>
	      <li><%= link_to "Contact", contact_path %></li>
	      <li><a href="http://news.railstutorial.jp/">News</a></li>
	    </ul>
	  </nav>
	</footer>

# RSpecを洗練させる

RSpecユーティリティ用ファイルを作成

	$ subl spec/support/utilities.rb
	
	def full_title(page_title)
	  base_title = "Ruby on Rails Tutorial Sample App"
	  if page_title.empty?
	    base_title
	  else
	    "#{base_title} | #{page_title}"
	  end
	end

RSpecをもっとシンプルに書く

````
$ subl spec/support/utilities.rb

require 'spec_helper'

describe "Static pages" do
  subject { page }

  describe "Home page" do

    before {visit root_path}
    it {should have_content('Sample App')}
    it {should have_title(full_title(''))}
    it {should_not have_title('| Home')}

  end

  describe "Help page" do

    before {visit help_path}
    it {should have_content('Help')}
    it {should have_title(full_title('Help'))}

  end

  describe "About page" do

    before {visit about_path}
    it {should have_content('About Us')}
    it {should have_title(full_title('About Us'))}

  end

  describe "Contact page" do

    before {visit contact_path}
    it {should have_content('Contact')}
    it {should have_title(full_title('Contact'))}

  end
end
````

# Usersコントローラ作成

## コントローラファイルを生成

	$ rails generate controller Users new --no-test-framework

## テスト作成

	$ rails generate integration_test user_pages
	$ subl spec/requests/user_pages_spec.rb
	
	require 'spec_helper'
	
	describe "User pages" do
	
	  subject { page }
	
	  describe "signup page" do
	    before { visit signup_path }
	
	    it { should have_content('Sign up') }
	    it { should have_title(full_title('Sign up')) }
	  end
	end

テスト実行

	$ bundle exec rspec spec/requests/user_pages_spec.rb
	=> 失敗する

	$ bundle exec rspec spec/ #と実行すると全てのテストを実行する。

## テストをパスするように修正

ルートを修正

	SampleApp::Application.routes.draw do
	  get "users/new"

	  root  'static_pages#home'
	  match '/help',    to: 'static_pages#help',    via: 'get'
	  match '/about',   to: 'static_pages#about',   via: 'get'
	  match '/contact', to: 'static_pages#contact', via: 'get'
	  match '/about', to: 'static_pages#about',  via: 'get'
	+  match '/signup',  to: 'users#new',  via: 'get'

ビューを修正

	+ <% provide(:title, 'Sign up') %>
	+ <h1>Sign up</h1>
	<p>Find me in app/views/users/new.html.erb</p>

テスト実行

	$ bundle exec rspec spec/requests/user_pages_spec.rb
	=> 成功する

HomeページのSignupボタンにリンクを設定

````
<div class="center hero-unit">
  <h1>Welcome to the Sample App</h1>

  <h2>
    This is the home page for the
    <a href="http://railstutorial.jp/">Ruby on Rails Tutorial</a>
    sample application.
  </h2>

  <%= link_to "Sign up now!", signup_path, class: "btn btn-large btn-primary" %>
</div>

<%= link_to image_tag("rails.png", alt: "Rails"), 'http://rubyonrails.org/' %>
````

# gitにコミット

	$ git add .
	$ git commit -m "Finish layout and routes"
	$ git checkout master
	$ git merge filling-in-layout