やること
- アプリケーションに
Bootstrap
フレームワークを組み込み、カスタムスタイルを追加 - 作成するページへのリンクをレイアウトに追加
- パーシャルRailsのルーティング、
Asset Pipeline
、Sass
-
RSpec
テクニックを用いたリファクタリング
構造を追加する
-
Bootstrap
- Twitter社のオープンソースのWebデザインフレームワーク
- 画面の変更
- リンク等のレイアウト変更
- 各種ページへのリンクを追加
- サインアップページへのリンクを追加
レイアウト変更のためのブランチを作成
$ git checkout -b filling-in-layout
ナビゲーションの追加
- リンクとスタイルを追加
- レイアウトファイルの
application.html.erb
にHTML構造を追加 -
<div>
タグの追加、CSSクラスの追加、サイトナビゲーションの追加
- レイアウトファイルの
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>
-
<!--[if lt IE 9]> - <!--[endif]>
- IEのバージョンが9未満の場合にのみ、囲まれている部分の行を実行
- HTMLの機能で、条件付コメントと呼ばれる
-
<header>
タグ- ページのトップに来るべき要素
- 3つのCSSクラスをスペース区切りで与えている
-
Bootstrap
において特別な意味を持つ
- ページのトップに来るべき要素
-
<div>
タグ- ドキュメントを別々のパーツに分けるのに利用
- 設定しているclassは
Bootstrap
において特別な意味を持つ-
navbar-inner
、container
-
-
<%= link_to "Home", '#' %>
- リンクを生成するヘルパー
- 第1引数:リンクテキスト
- 第2引数:URL
- 第3引数(オプション):オプションハッシュ。HTMLオプションを柔軟に追加できる
-
<nav>
タグ- 内部がナビゲーションリンクであることを表す
-
<ul>
タグのnav
とpull-right
クラスはBootstrap
において特別な意味を持つ
navタグの埋め込みRuby評価後のソース
<nav>
<ul class="nav pull-right">
<li><a href="#">Home</a></li>
<li><a href="#">Help</a></li>
<li><a href="#">Sign in</a></li>
</ul>
</nav>
app/views/static_pages/home.html.erb
<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/' %>
-
hero-unit
、btn
、btn-primary
クラス-
Bootstrap
において特別な意味を持つ
-
-
image_tag
ヘルパー-
img
タグの生成 - 第1引数:画像ファイル名
- 第2引数:ハッシュ
-
image_tagの埋め込みRuby評価後のソース
<img alt="Rails" src="/assets/rails.png" />
BootstrapとカスタムCSS
-
Bootstrap
を使用するメリット- 洗練されたWebデザインとUI要素を簡単にHTML5アプリに追加できる
- カスタムCSSルールと
Bootstrap
を組合わせて、サンプルアプリにスタイルを追加
-
Bootstrap
の導入-
bootstrap-sass gem
を使用してRailsアプリに導入
-
-
Bootstrap
の言語-
LESS CSS
言語 - Railsの
Asset Pipeline
はSass
言語をサポート -
bootstrap-sass
でLESS
をSass
に変換する
-
Gemfileにbootstrap-sassを追加
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.0.4'
gem 'bootstrap-sass', '2.3.2.0'
gem 'sprockets', '2.11.0'
(中略)
config/application.rb ※Rails4.0以降の場合のみ必要
require File.expand_path('../boot', __FILE__)
require "active_record/railtie"
require "action_controller/railtie"
require "action_mailer/railtie"
require "sprockets/railtie"
Bundler.require(*Rails.groups)
module SampleApp
class Application < Rails::Application
config.assets.precompile += %w(*.png *.jpg *.jpeg *.gif)
end
end
Bootstrapの組み込み
# Bootstrapのインストール
$ bundle install
# Webサーバの再起動
# Ctrl+CなどでRailsサーバを停止
$ rails s &
- カスタムCSS用のファイル
-
app/assets/stylesheets/custom.css.scss
を作成 -
Asset Pipeline
の一部であり、上記ディレクトリに格納されたスタイルシートはapplication.css
の一部として自動的にWebサイトのレイアウトにインクルードされる -
.css
が含まれているのでCSSファイル -
.scss
が含まれているのでSass
を記述できるCSSファイル(Sassy CSS: Scss) -
@import
を使って、Bootstrap
をインクルードする
-
app/assets/stylesheets/custom.css.scss
@import "bootstrap";
app/assets/stylesheets/custom.css.scssにスタイルを追加
@import "bootstrap";
html {
overflow-y: scroll;
}
/*
ページ上部に60ピクセルの余白を追加
headerタグにnavbar-fixed-topクラスが与えられているので、
これに従いBootstrapはナビゲーションバーをページ上部に固定し、
ナビゲーションバーの下に余白を置いて主要部分から分離する
*/
body {
padding-top: 60px;
}
section {
overflow: auto;
}
textarea {
resize: vertical;
}
/*
centerクラスにtext-align: centerプロパティを関連付けている
centerクラスに属しているタグの内側にある要素は全てセンタリングされる
*/
.center {
text-align: center;
}
.center h1 {
margin-bottom: 10px;
}
app/assets/stylesheets/custom.css.scssにタイポグラフィーの設定を追加
@import "bootstrap";
(中略)
/* 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;
}
app/assets/stylesheets/custom.css.scssにサイトロゴの設定を追加
@import "bootstrap";
(中略)
/* 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)
-
現状の問題点
-
HTML shim
だけで3行使ってしまっている-
IE
特有の文法を使用してしまっている
-
- HTMLヘッダーは論理的な単位を形成するため、一箇所にまとめる必要がある
-
-
パーシャル機能によって整理する
-
render
を使い、IE固有の設定およびヘッダー部分の記述を変更
-
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 %>
</div>
</body>
</html>
-
<%= render 'layouts/shim' %>
-
app/views/layouts/_shim.html.erb
というファイルを検索してその内容を評価し、結果をビューに挿入 - パーシャルの命名規則として、ファイル名に
_
をつける
-
app/views/layouts/_shim.html.erbでパーシャルを作成
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
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>
- フッターの作成
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>
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>
- フッターを追加した画面を確認
- フッターのスタイルを追加
app/assets/stylesheets/custom.css.scss
@import "bootstrap";
(中略)
/* 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
-
Asset Pipeline
- CSS、Javascript、画像などの静的コンテンツの生産性と管理を大幅に強化する機能
-
Sass
- CSS生成ツール
Asset Pipeline
- 主要な機能
- アセットディレクトリ
- マニフェストファイル
- プリプロセッサエンジン
- アセットディレクトリ
- Rails3.0以前のバージョン
public/stylesheets
public/javascripts
public/images
- Rails3.1以降のバージョン - 目的別に静的ファイルを分類。それぞれに
stylesheets
、javascripts
、images
ディレクトリが存在する-
app/assets
:現在のアプリケーション固有のアセット -
lib/assets
:自身の開発チームによって作成されたライブラリ用のアセット -
vendor/assets
:サードパーティーのアセット
-
- Rails3.0以前のバージョン
-
マニフェストファイル
- アセットディレクトリのファイルをどのように1つのファイルにまとめるかをRailsに指示
- 実際にまとめるのは
Sprockets gem
- CSSとJavaScriptには適用されるが、画像ファイルには適用されない
-
*= require_tree .
-
app/assets/stylesheets
ディレクトリの全てのCSSをアプリケーションCSSにインクルードすることを指す
-
-
*= require_self
- CSSの読み込みの際に、
application.css
自身もインクルードする
- CSSの読み込みの際に、
-
今回は特に変更しない
マニフェストファイルapp/assets/stylesheets/application.css
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the top of the
* compiled file, but it's generally better to create a new file per style scope.
*
*= require_self
*= require_tree .
*/
- プリプロセッサエンジン
- 必要なアセットをディレクトリに配置してまとめた後、Railsは様々なプリプロセッサエンジンを介してそれらを実行
- ブラウザに配信できるようにマニフェストファイルを用いて結合し、際とテンプレート用に準備する
- Railsでどのプリプロセッサを使用するかの判定
- ファイルの拡張子で判断
-
.scss
:Sass -
.coffee
:CoffeeScript -
.erb
:埋め込みRuby(ERb)
-
- 繋げて実行することができる
-
foobar.js.coffee
:CoffeeScriptプロセッサ経由で実行される -
foobar.js.erb.coffee
:CoffeeScriptとERbの両方で実行される- 右から左に実行されるので、CoffeeScript => ERbの順に実行される
-
- ファイルの拡張子で判断
-
Asset Pipeline
のメリット- 本番のアプリケーションで効率的になるように最適化されたアセットも自動的に生成される
- 従来のCSSとJavaScriptを整理する手法
- 機能を個別のファイルに分割し、読みやすいフォーマットに整形
- プログラマにとっては可読性があるが、圧縮されていないので本番環境では非効率
-
Asset Pipeline
- 全てのスタイルシートを1つのCSSファイル(
application.css
)にまとめる - 全てのJavaScriptファイルを1つのJSファイル(
javascripts.js
)にまとめる - それらのファイル全てに対して不要な空白を取り除く
- ファイルサイズを最小化する
- 全てのスタイルシートを1つのCSSファイル(
- プログラマにとっては見やすく分割されたフォーマットのファイルを提供
- 本番環境に対しては最適化された1つのファイルを提供
Sass
-
Sass
とは- スタイルシートを記述するための言語
- CSSよりも多くの点で強化されている
- 本節ではネストと変数について説明
- ミックスインについては第7章で説明
- SCSSフォーマットに対応
- CSS本体を抽象化したフォーマット
- CSSに新しい機能を追加しただけで、新しい構文を定義したものではない
- 拡張子は
.scss
ネスト
- ネスト
- スタイルシート内に共通のパターンがある場合、要素をネストすることができる
通常のCSSの表記:.centerへのルール
.center {
text-align: center;
}
.center h1 {
margin-bottom: 10px;
}
Sassでの表記:.centerをネストして記載
.center {
text-align: center;
h1 {
margin-bottom: 10px;
}
}
通常のCSSでの表記:#logoというidが重複
// #logoの定義
# 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;
}
Sassでの表記:親属性を参照するのに&を使用
# 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;
&:hover {
color: #fff;
text-decoration: none;
}
}
フッターのCSS
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;
}
フッターのCSSをSCSSで記載
footer {
margin-top: 45px;
padding-top: 5px;
border-top: 1px solid #eaeaea;
color: #999;
a {
color: #555;
&:hover {
color: #222;
}
}
small {
float: left;
}
ul {
float: right;
list-style: none;
li {
float: left;
margin-left: 10px;
}
}
}
変数
- 変数
- 同じ値を変数として定義・参照することで、冗長なコードを削除し、より自由な表現を可能とする
- 繰り返し使わないとしても、可読性がよくなるので定義すべき
-
Bootstrap
フレームワークにおいても多くの色などに対して変数名を定義している- LESS変数一覧を参照
-
bootstrap-sass
というgemを使用することで、Sassでも同様の変数が使える
通常のCSS:#999を複数個所で使用
h2 {
color: #999;
}
footer {
color: #999;
}
SCSS:#999を変数として定義
$lightGray: #999;
h2 {
color: $lightGray;
}
footer {
color: $lightGray;
}
SCSS:Bootstrapフレームワークで定義している変数を利用
h2 {
color: $grayLight;
}
footer {
color: $grayLight;
}
- ネスト・変数を使用して、SCSSファイルを書き換える
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 #eaeaea;
color: $grayLight;
a {
color: $gray;
}
&:hover {
color: $grayDarker;
}
small {
float: left;
}
ul {
float: right;
list-style: none;
li {
float: left;
margin-left: 10px;
}
}
}
レイアウトのリンク
-
レイアウトのリンク
- 現時点では全て#
-
<a href="/static_pages/about">About</a>
はいけてない- Railsでは
/about
となるようにすべき
- Railsでは
- Railsの場合、
<%= link_to "About", about_path %>
などとする- 可読性が増す
-
about_path
に定義しておくことで、URLを変更したい場合にも容易に変更できる
-
サンプルアプリケーションの全てのリンクリスト
ページ | URL | 名前付きルート |
---|---|---|
Home | / | root_path |
About | /about | about_path |
Help | /help | help_path |
Contact | /contact | contact_path |
Sign up | /signup | signup_path |
Sign in | /signin | signin_path |
- Contactは既に第3章で作成済み
名前付きルートのテスト
- テストコードの修正
-
visit '/static_pages/about'
となっているような部分をvisit about_path
に置き換える
-
- テストを実行するとエラーになる
bundle exec rspec spec/requests/static_pages_spec.rb
spec/requests/static_pages_spec.rb:アドレスを名前付きルートに変更
require 'spec_helper'
describe "StaticPages" do
let(:base_title) { "Ruby on Rails Tutorial Sample App" }
describe "Home page" do
it "should have the content 'Sample App'" do
visit root_path
expect(page).to have_content('Sample App')
end
it "should have the title 'Home'" do
visit root_path
expect(page).to have_title("#{base_title} - Home")
end
end
describe "Help page" do
it "should have the content '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("#{base_title} - Help")
end
end
describe "About page" do
it "should have the content 'About Us'" do
visit about_path
expect(page).to have_content('About Us')
end
it "should have the title 'About'" do
visit about_path
expect(page).to have_title("#{base_title} - About Us")
end
end
describe "Contact page" do
it "should have the content 'Contact'" 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("#{base_title} - Contact")
end
end
end
Railsのルート
- RailsがURLマッピングに使用するファイル
config/routes.rb
- 現在のURLマッピングの設定
get 'static_pages/help'
- 名前付きルートに変更した場合
-
match '/help', to: 'static_pages#help', via: 'get'
-
/help
へのGETリクエストにマッチ -
StaticPages
コントローラのhelp
アクションにルーティングされる
-
-
match '/help'
というコードにより、下記の名前付きルートが自動生成されるabout_path -> '/about'
about_url -> 'http://localhost:3000/about'
-
config/routes.rb:名前付きルートの定義
SampleApp::Application.routes.draw do
match '/help', to: 'static_pages#help', via: 'get'
match '/about', to: 'static_pages#about', via: 'get'
match '/contact', to: 'static_pages#contact', via: 'get'
end
- 上記変更後にテストを再実行
-
home
以外はOKになる
-
-
home
をconfig/routes.rb
に記載するには-
root 'static_pages#home'
と書く -
match '/', to: 'static_pages#home', via: 'get'
でも書けるが、上記が推奨 -
root 'static_pages#home'
というコードにより、下記の名前付きルートが自動生成されるroot_path -> '/'
root_url -> 'http://localhost:3000/'
-
-
root
の設定を追加後にテストを実行すると全てOKになる
config/routes.rb:homeの設定を追加
SampleApp::Application.routes.draw do
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'
end
名前付きルート
-
link_to
メソッドの変更- ヘッダーのパーシャルとフッターのパーシャルを修正
- 当変更後、
Home
、Help
、About
、Contact
へのリンクが有効になる
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>
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のテスト内容が冗長で繰り返しが多くなってきている
spec/requests/static_pages_spec.rbの抜粋
describe "Home page" do
it "should have the content 'Sample App'" do
visit root_path
expect(page).to have_content('Sample App')
end
it "should have the title 'Home'" do
visit root_path
expect(page).to have_title("#{base_title} - Home")
end
end
-
visit
が重複している-
before
ブロックを使用して冗長箇所を除去する
-
spec/requests/static_pages_spec.rb:beforeブロックに変更
describe "Home page" do
before { visit root_path }
it "should have the content 'Sample App'" do
expect(page).to have_content('Sample App')
end
it "should have the title 'Home'" do
expect(page).to have_title("#{base_title} - Home")
end
end
- どっちのテストも
page
変数を使用する-
subject
ブロックを使用し、テストの主題がpage
であることを定義する
-
-
it "should have the content 'Sample App!'" do
とexpect(page).to have_content('Sample App')
は同じことを言っている-
it
メソッドの別のものを使用
-
spec/requests/static_pages_spec.rb:subjectブロックの使用とitメソッドの変更
subject { page }
describe "Home page" do
before { visit root_path }
it { should have_content('Sample App') }
it { should have_title("#{base_title} - Home") }
end
-
let
ブロックでbase_title
を定義しているが、ユーティリティクラスに持たせたい-
spec/support
ディレクトリにutilities.rb
ファイルを作成し、full_title
メソッドを定義 -
spec/support
ディレクトリはRSpecによって自動的に読み込まれる
-
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
spec/requests/static_pages_spec.rb:ユーティリティクラスを参照
subject { page }
describe "Home page" do
before { visit root_path }
it { should have_content('Sample App') }
it { should have_title(full_title('Home')) }
end
- 上記を踏まえて、テストクラスをリファクタリング
- 修正後にテストを実行して、正常終了することを確認
spec/requests/static_pages_spec.rb:リファクタリング
require 'spec_helper'
describe "StaticPages" do
subject { page }
describe "Home page" do
before { visit root_path }
it { should have_content('Sample App') }
it { should have_title(full_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
ユーザー登録
- ユーザー登録ページへのルーティングを作成
- 2番目のコントローラを作成する必要がある
Usersコントローラ
Usersコントローラの生成(newアクションを追加)
$ rails generate controller Users new --no-test-framework
create app/controllers/users_controller.rb
route get "users/new"
invoke erb
create app/views/users
create app/views/users/new.html.erb
invoke helper
create app/helpers/users_helper.rb
invoke assets
invoke coffee
create app/assets/javascripts/users.js.coffee
invoke scss
create app/assets/stylesheets/users.css.scss
ユーザー登録用URL
- テスト用ファイルの作成
テスト用ファイルの作成
$ rails generate integration_test user_pages
invoke rspec
create spec/requests/user_pages_spec.rb
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
-
StaticPages
も含めてテストを実施bundle exec rspec spec/
-
user_pages_spec.rb
部分がエラーになる
-
ルーティングの設定
-
/signup
のルートを追加
-
config/routes.rb
SampleApp::Application.routes.draw do
get "users/new"
root 'static_pages#home'
match '/signup', to: 'users#new', via: 'get'
match '/help', to: 'static_pages#help', via: 'get'
match '/about', to: 'static_pages#about', via: 'get'
match '/contact', to: 'static_pages#contact', via: 'get'
end
- ユーザ登録ページのスタブを作成
- テストを実施し、正常終了することを確認
app/views/users/new.html.erb
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>
<p>Find me in app/views/users/new.html.erb</p>
-
home
のページからのSign up
へのリンクを修正
app/views/static_pages/home.html.erb
<% provide(:title, '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!", signup_path, class: "btn btn-large btn-primary" %>
</div>
<%= link_to image_tag("rails.png", alt: "Rails"), 'http://rubyonrails.org/' %>
コミット
コミット、デプロイ
$ git add .
$ git commit -m "Finish layout and routes"
$ git checkout master
$ git merge filling-in-layout
$ git push
$ git push heroku
$ heroku open
# エラーが発生する場合はログを確認
$ heroku logs
演習問題
Shared Examples
- Shared Examples
- 同じようなテストを複数箇所で実施する場合に使用
- テンプレートのテストケースを記載し、変数部分だけを各メソッドで
let
にて設定することで、同じようなテストケースの記載を省くことができる
spec/requests/static_pages_spec.rbの修正前
describe "StaticPages" do
subject { page }
describe "Home page" do
before { visit root_path }
it { should have_content('Sample App') }
it { should have_title(full_title('Home')) }
end
end
- Shared Examples適用後
- Helpなど、他のページにも同様に適用
spec/requests/static_pages_spec.rbの修正後
describe "StaticPages" do
subject { page }
shared_examples_for "all static pages" do
it { should have_content(heading) }
it { should have_title(full_title(page_title)) }
end
describe "Home page" do
before { visit root_path }
let(:heading) { 'Sample App' }
let(:page_title) { '' }
it_should_behave_like "all static pages"
end
end
click_linkによるレイアウトのリンクのテスト
-
click_link
- リンクが実際に正しいページへのリンクになっているかをテスト
spec/requests/static_pages_spec.rbにリンクのテストを追加
describe "StaticPages" do
it "should have the right links on the layout" do
visit root_path
click_link "About"
expect(page).to have_title(full_title('About Us'))
click_link "Help"
expect(page).to have_title(full_title('Help'))
click_link "Contact"
expect(page).to have_title(full_title('Contact'))
click_link "Home"
expect(page).to have_title(full_title(''))
click_link "Sign up now!"
expect(page).to have_title(full_title(''))
click_link "sample app"
expect(page).to have_title(full_title(''))
end
end
ヘルパーメソッドのテストを作成
spec/helpers/application_helper_spec.rb
require 'spec_helper'
describe ApplicationHelper do
it "should include the page title" do
expect(full_title("foo")).to match(/foo/)
end
it "should include the base title" do
expect(full_title("")).to match(/^Ruby on Rails Tutorial Sample App/)
end
it "should not include a bar for the home page" do
expect(full_title("")).not_to match(/-/)
end
end
spec/support/utilities.rbの中身を変更(ApplicationHelperをincludeするだけに変更)
include ApplicationHelper