#近況報告
エンジニア転職成功しました。YouTubeもはじめました。
著者略歴
YUUKI
ポートフォリオサイト:Pooks
現在:RailsTutorial2周目
#第5章 難易度 ★★ 3時間
挫折しないRailsチュートリアルの進め方を先にお読みください↓↓
この章ではHTML/CSSの基礎からアセットパイプラインの概要、Sass、Bootstrapの使い方
効率よくコーディングする為のパーシャル、統合テストなどアプリケーション作成に必要な基礎スキルを身に付ける。
#レイアウトを作成する
この章では、デザイン関係の部分を弄る。
WebデザインフレームワークであるBootstrap
を使い、パーシャル機能を使ってレイアウトのコードを整える。さらに、統合テストも取り扱っていくとのこと。
##構造を追加する
ユーザーインターフェースの概要をできるだけ早い段階で把握しておくために、「モックアップ」を作成する。
このモックアップは、実装後のアプリケーションの外観をスケッチして使っていく。
Homeページのモックアップ
出典:図 5.1: サンプルアプリケーションのHomeページのモックアップ
###ナビゲーション
サンプルアプリケーションにリンクとスタイルを追加するために、application.html.erb
にHTML構造を追加する。主にdivタグやCSSクラス、サイトナビゲーションの起点となる領域の追加も含まれる。
<DOCTYPE html>
<html>
<head>
<title><%= full_title(yield(:title)) %></title>
<%= scrf_meta_tags %>
<%= stylesheet_link_tag 'application', media: 'all',
'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application',
'data-turbolinks-track': 'reload' %>
<!--[if It IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/r29/html5.min.js">
</script>
<![endif]-->
</head>
<body>
<header class="navbar navbar-fixed-top navbar-inverse">
<div class="container">
<%= link_to "sample app", '#', id: "logo" %>
<nav>
<ul class="nav navbar-nav navbar-right">
<li><%= link_to "Home", '#' %></li>
<li><%= link_to "Help", '#' %></li>
<li><%= link_to "Log in", '#' %></li>
</ul>
</nav>
</div>
</header>
<div class="container">
<%= yield %>
</div>
</body>
</html>
長いけど、まず重要なコードはこれ。
<!--[if It IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/r29/html5.min.js">
</script>
<![endif]-->
このJavaScriptのコードで、旧式のIEでもサポート出来るようにする。
<!--[if It IE 9]>
この部分はIEのバージョンが9より小さい場合、囲まれている部分を実行する。
これを条件付きコメント
と言う。
バージョンが9未満の場合のみHTML5 shim
を読み込める。
headerタグの部分。
<header class="navbar navbar-fixed-top navbar-inverse">
<div class="container">
<%= link_to "sample app", '#', id: "logo" %>
<nav>
<ul class="nav navbar-nav navbar-right">
<li><%= link_to "Home", '#' %></li>
<li><%= link_to "Help", '#' %></li>
<li><%= link_to "Log in", '#' %></li>
</ul>
</nav>
</div>
</header>
classとidが幾つか割り振られている。
HTML5では、全体でdivタグを扱うのではなく、header要素、nav要素、section要素が新たに追加されたのでこれを使う。
headerタグとdivタグにcontainerというクラスが与えられているが、これはBootstrapにおいても特別な意味を持つ。
<%= link_to "sample app", '#', id: "logo" %>
<nav>
<ul class="nav navbar-nav navbar-right">
<li><%= link_to "Home", '#' %></li>
<li><%= link_to "Help", '#' %></li>
<li><%= link_to "Log in", '#' %></li>
link_to
は埋め込みRubyであり、第一引数にテキスト、第二引数にURLを付ける。
#
はWebデザインで一般に使われるスタブ用のURLである。
第三引数はオプションハッシュ。CSS id logoを指定している。
続いて、navタグを見てみる。
<nav>
<ul class="nav navbar-nav navbar-right">
<li><%= link_to "Home", '#' %></li>
<li><%= link_to "Help", '#' %></li>
<li><%= link_to "Log in", '#' %></li>
</ul>
</nav>
ulタグの三つのclassnav navbar-nav navbar-right
がBootstrapにおいても特別な意味を持つ。
どうやらBootstrapのCSSを追加したときに、この三つのスタイルが自動的に適用される。
ブラウザからソースを見た際、上記のHTMLは以下のように変化する。
<nav>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Home</a></li>
<li><a href="#">Help</a></li>
<li><a href="#">Log in</a></li>
</ul>
</nav>
これはRailsが埋め込みRubyを評価しているため、ブラウザに返されるのはHTMLに変わる。
そして重要なのがこれ
<div class="container">
<%= yield %>
</div>
container
クラスもBootstrapで適用される。
さらに、yieldメソッドはWebサイトのレイアウトページごとの内容を挿入する。
これである程度のレイアウトは完成。
<div class="center jumbotron">
<h1>Welcome to the Sample App</h1>
<h2>
This is the home page for the
<a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
sample application.
</h2>
<%= link_to "Sign up now!", '#', class: "btn btn-lg btn-primary" %>
</div>
<%= link_to image_tag("rails.png", alt: "Rails logo"),
'http://rubyonrails.org/' %>
homeページのレイアウトも確認。
これらで使っているクラスは全てBootstrapに置いて特別な意味を持つ。
2番目のlink_toでは画像ファイルのパスと任意のオプションハッシュをとるimage_tag
ヘルパーの能力が示される。このヘルパーでは、シンボルを使ってalt属性などを設定できる。
ここで、link_toで設定している画像をインストールする。
Cloud9の場合、curl(カール)コマンドで簡単に画像を取得できる。
curl -o app/assets/images/rails.png -OL railstutorial.jp/rails.png
image_tag
ヘルパーを使って画像ファイルを読み込むので、画像をアセットパイプラインを通してapp/assets/images/
ディレクトリの中から探してくれる。
んで、rails s
でサーバー起動して確認してみる。
今回自分なりに弄ってみた。
image_tagの効果を確かめるべく、HTMLソースを確認。
<img alt="Rails logo" src="/assets/yuuki-e83954ed50d243b8f3edb6aee76f03768aed99b6436f49906ab2f8c56e6d32c9.png">
画像の所を確認して見入るとこんな表示になってる。
このe8395~
ってのは、例えばこの画像ファイルを新しい画像に更新した時、ブラウザ内に保存されたキャッシュを意図的にヒットさせないようにする仕組みとのこと。
また、src属性にはimages
というディレクトリ名が含まれていない点にも注目。
これはassetsディレクトリ内の他のディレクトリでも同様で、高速化のための仕組み。
というのも、この仕組みを使うことでassetsディレクトリ直下の画像をapp/assets/imagesディレクトリにある画像と紐づけている。
ブラウザからみると、全てのファイルが同じディレクトリにあるように見えるようになり、階層構造で言う所の深い部分のファイルまでロードせずに済み、フラットなディレクトリ構成を実現。ファイルをより高速にブラウザに渡すことが可能となる。
ここで、演習の通り猫ちゃん画像をダウソして表示してみる。
ふむ。
###BootstrapとカスタムCSS
先ほどの部分でHTML要素にCSSクラスを関連付けたが、これらの殆どはBootstrap用のクラスである。
このBootstrapはカスタムCSSルールと合わせて使用する。
Bootstrapの利点はレスポンシブデザインにできるという点。
という訳で早速Bootstrapを追加する。
gemを使ってインストール。
gem 'bootstrap-sass', '3.3.7'
$ bundle install
ここで、カスタムCSSを動かすた目にカスタムCSSファイルを作成。
touch app/assets/stylesheets/custom.scss
ここで紹介されているapp/assets/stylesheets/
はAsset Pipelinenの一部。
このディレクトリに置かれたスタイルシートは、application.css
の一部としてWebサイトのレイアウトに読み込まれる。
また、scss
という拡張子はSassと呼ばれるCSS拡張言語で、アセットパイプラインはこのファイルの拡張子を見て、Sassを処理できるようにしている。(bootstrap-sass gemが動作するために必要)
@import "bootstrap-sprockets";
@import "bootstrap";
@importを使ってbootstrapを読み込ませる。
これでhomeページを確認。
何も指定してないのに勝手にデザインが出来あがるという。
指示通りにcustom.scss
に以下を記入。
/* universal */
body {
padding-top: 60px;
}
section {
overflow: auto;
}
textarea {
resize: vertical;
}
.center {
text-align: center;
}
.center h1 {
margin-bottom: 10px;
}
CSSの形式は一貫しており、CSSルールでは一般に
class,id,HTMLタグ,またはそれらの組み合わせ、のいずれかを指定し、
その後ろにスタイリングコマンドを記述する。例えば次のコマンド
body {
padding-top: 60px;
}
bodyセレクタのpadding-topプロパティに60pxという値を設定。
つまり、bodyの上側に60pxの余白を追加するという意味だ。ただし、headerタグにnavbar-fixed-top
クラスが付与されている為、Bootstrapがナビゲーションバーをページ上部に固定し、その下に60pxの余白が与えられる。
次にこちらのコード
.center {
text-align: center;
}
ここで.
が付いている理由は、centerがクラスであるということ。先ほどのbody
はタグなので.
は付けない。
ちなみにidにセレクタを設定する場合は先頭に#
を付ける。
上記のコードでcenterクラスの内側の要素が全て中央揃えになる。
さらにこちらのコードを追加。
/* タイポグラフィ */
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: #777;
}
p {
font-size: 1.1em;
line-height: 1.7em;
}
これはタイポグラフィと言って、テキストや画像の体裁を決めるもの。予め書いておくことで、個別で文字サイズなどを指定せずに済む。
元々Bootstrapには洗練されたタイポグラフィを利用できるCSSルールがあるが、今回はこのように追加でテキストの見栄えを変えてみる。
ここでhomeページを確認してみると、さらに洗練されたデザインになっている。
さらに下記のコードを追加。
/* 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;
}
#logo:hover {
color: #fff;
text-decoration: none;
}
colorプロパティの値「#fff」は白色。
HTMLの色は16進数の三つの数値の組み合わせで表現され、赤,緑,青の順で、三原色にコード化することができる。
*fは16進数で15に値する。また、本来whiteは#ffffffだがここでは短縮記法にしている。
ここで、演習をやってみる。
猫画像をコメントアウトしてみる。
(今回はプロフィール画像をコメントアウトする)
<%#= link_to image_tag("yuuki.png", alt: "Rails logo"),
'https://twitter.com/bitcoinjpnnet', target: "_blank" %>
このように埋め込みRubyのコードは%と=の間に#
を記入することで簡単にコメントアウト出来る。
次にimgセレクタをdisplay noneしてみる。
img {
display: none;
}
全ての画像が消えていることを確認。
###パーシャル
先程のHTML修正(shim)ではそれだけでも3行を有し、無駄が多い。これを上手く隠したり、論理的な単位を形成する為、一箇所にコードをまとめる必要がある。
その為に、Railsではpartialと呼ばれている機能を使う。
<DOCTYPE html>
<html>
<head>
<title><%= full_title(yield(:title)) %></title>
<%= csrf_meta_tags %>
<%= stylesheet_link_tag 'application', media: 'all',
'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application',
'data-turbolinks-track': 'reload' %>
<%= render 'layouts/shim' %>
</head>
<body>
<%= render 'layouts/header' %>
<div class="container">
<%= yield %>
</div>
</body>
</html>
パーシャルの読み込みにはrender
メソッドを使う。
パーシャルでは、ファイル名の先頭に_(アンダースコア)を付与する普遍的な命名規則がある。
_shim.html.erb
と_header.html.erb
というファイル名でパーシャルを作成してみる。
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/r29/html5.min.js">
</script>
<![endif]-->
<header class="navbar navbar-fixed-top navbar-inverse">
<div class="container">
<%= link_to "sample app", '#', id: "logo" %>
<nav>
<ul class="nav navbar-nav navbar-right">
<li><%= link_to "Home", '#' %></li>
<li><%= link_to "Help", '#' %></li>
<li><%= link_to "Log in", '#' %></li>
</ul>
</nav>
</div>
</header>
さらに、footer用のパーシャルも作成。
<footer class="footer">
<smail>
The <a href="https://railstutorial.jp/">YUUKIのポートフォリオ</a>
by <a href="https://twitter.com/bitcoinjpnnet">YUUKI</a>
</smail>
<nav>
<ul>
<li><%= link_to "About", '#' %></li>
<li><%= link_to "Contact", '#' %></li>
<li><a href="https://webnewage.com/">YUUKIのブログ</a></li>
</ul>
</nav>
</footer>
footer用のscssも追加。
/* footer */
footer {
margin-top: 45px;
padding-top: 5px;
border-top: 1px solid #eaeaea;
color: #777;
}
footer a {
color: #555;
}
footer a:hover {
color: #222;
}
footer smail {
float: left;
}
footer ul {
float: right;
list-style: none;
}
footer ul li {
float: left;
margin-left: 15px;
}
演習通りにrails_defaultパーシャルも作成して、headタグをrenderに置き換える。
<%= render 'layouts/rails_default' %>
##Sassとアセットパイプライン
実はアセットパイプラインは最近Railsに追加された機能。
Rails開発者の視点からは、
- アセットディレクトリ
- マニフェストファイル
- プリプロセッサエンジン
この三つの主要な機能が理解の対象となる。
###アセットディレクトリ
Railsのアセットパイプラインでは、静的ファイルを目的別に三つのディレクトリに分類する。
- app/assets 現在のアプリケーション固有のアセット
- lib/assets 自分の開発チームによって作成されたライブラリ用のアセット
- vendor/assets サードパーティのアセット
これらのディレクトリには、それぞれのアセットクラス用のサブディレクトリがある。
app/assetの場合
$ ls app/assets
config images javascripts stylesheets
このようなサブディレクトリがある。
つまり、custom.scss
はサンプルアプリケーション固有のアセットなので、上記の場所に配置されているということ。
###マニフェストファイル
それぞれのアセットファイルをどのように1つにまとめるのかをRailsに指示するファイルのこと。
実際にアセットをまとめる処理を行うのはSprocketsと言うgem。
ちなみに、マニフェストファイルはCSSとJavaScriptには適用されるが、画像ファイルには適用されない
一つの具体例がコレ。
アプリケーション固有の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, or any plugin's
* vendor/assets/stylesheets directory 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 bottom of the
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
* files in this directory. Styles in this file should be added after the last require_* statement.
* It is generally better to create a new file per style scope.
*
*= require_tree .
*= require_self
*/
CSSコメントの最後の方に注目。
*= require_tree .
*= require_self
*/
この部分は、Sprocketsgが適切なファイルを読み込むために使われる。
*= require_tree .
はapp/assets/stylesheets
ディレクトリ内の全てのCSSファイルが、アプリケーションCSS
に含まれるようにしている。
*= require_self
はCSS読み込みシーケンスの中で、application.css
自身もその対象に含まれている。
Railsには実用的なデフォルトのマニフェストファイルが付属している。
###プリプロセッサエンジン
必要なアセットをディレクトリに配置してまとめたあとは、
プリプロセッサエンジンを介してブラウザに配信できるようにそれらをマニフェストファイルを用いて統合し、サイトテンプレート用に準備する。
Railsではどのプリプロセッサを使うのか、ファイルの拡張子で判断する。
- .scss
- .coffee
- .erb
の三つが一般的な拡張子である。
プリプロセッサエンジンではメソッドチェーンが使える為、繋げて実行することができる
例
foobar.js.erb.coffee
この拡張子だと、erbとcoffee両方のプロセッサ経由で実行される。
なお、コードは右から左に実行されるので、coffee→erbという実行手順となる。
###本番環境での効率性
Asset Pipelineの最大のメリットは開発環境と本番環境それぞれで最高の環境が用意できることである。
具体的には、開発環境ではCSSやJavaScriptを個別のファイルで用意し、本番環境ではAsset PipelineでそれぞれのCSSファイルを1つのCSSファイルapplication.css
にまとめ、全てのJavaScriptファイルを一つのJSファイルjavascripts.js
にまとめる。
さらに、それら全てのファイルのインデントや空白を取り除く処理を行い、ファイルを最小化する。
Asset Pipelineの結果、ユーザーから見て素早い動きでありながら開発環境ではプログラマに取って書きやすい形態を取ることができる。
###Sass
SassはCSSに拡張的な機能の付いた言語。
Sassが提供する二つの重要な機能に、ネスト
と変数
がある。
SassはSCSSというフォーマットに対応している。すなわち、.scss
という拡張子はSCSSである。
CSSファイルはSCSSファイルとしても扱うことができるため、互換性のあるフォーマットになっている。
(RailsTutorialではBootstrapの恩恵を得る為に最初からSCSSを使っている)
Railsのアセットパイプラインは.scss
という拡張子を持つファイルをSassを使って自動的に処理してくれる。
つまり、custom.scss
ファイルはSassプリプロセッサ
によって前処理され、その後ブラウザへの配信に備えてパッケージ化される。
####ネスト
要素を入れ子構造にすることである。
従来のCSSでは
.center {
text-align: center;
}
.center h1 {
margin-bottom: 10px;
}
このように分けて書いていた物を
.center {
text-align: center;
h1 {
margin-bottom: 10p;
}
}
このように書ける。
ネストの内側にあるh1は、.centerのルールを継承しているという点に注目。
属性もネストできる。
#logo {
float: left;
margin-right: 10px;
font-size: 1.7em;
color: #fff;
text-transform: uppercase;
letter-spacing: -1px;
padding-top: 9px;
font-weight: bold;
}
#logo:hover {
color: #fff;
text-decoration: none;
}
このように分けていたhover属性を
#logo {
float: left;
margin-right: 10px;
font-size: 1.7em;
color: #fff;
text-transform: uppercase;
letter-spacing: -1px;
padding-top: 9px;
font-weight: bold;
& hover {
color: #fff;
text-decoration: none;
}
}
%
(アンパーサンド)でネストできる。
こうするとSassがSCSSをCSS変換するときに&:hover
を'#logo:hover`に置き換えている。
今度はfooterのCSSをSCSSを用いてネスト構造にしてみる。
footer {
margin-top: 45px;
padding-top: 5px;
border-top: 1px solid #eaeaea;
color: #777;
a {
color: #555;
&:hover {
color: #222;
}
}
smail {
float: left;
}
ul {
float: right;
list-style: none;
li {
float: left;
margin-left: 15px;
}
}
}
CSSが適切に動作していればOK.
####変数
Sassではなんと変数が定義できる(これは便利や)
例えばこちらの冗長なコード。
h2 {
color: #777;
}
footer {
color: #777;
}
同じプロパティの値が設定されている。
Sassでは、このような値#777
を変数として定義し、変数名を与えることができる。
$light-gray: #777;
これを使ってSCSSを次のように書き直すことができる。
$ligth-gray: #777;
h2 {
color: $light-gray;
}
footer {
color: $ligth-gray;
}
パッと見面倒臭そうだが、#777
と記述するより`$light-gray'の方が色がわかりやすい(灰色)ので、変数名を与えること有用である。
(Bootstrapフレームワークでは、多くの色に対して変数名が定義されている)
定義されている変数はLESS変数一覧
で参照できる。
また、bootstrap-sass
というgemを使えば、Sassでも同様の変数が使える。
LESSとSassの違いとして、@マークが$マークに変わっていることなどが挙げられる。
@gray-light: #777; #LESS
$gray-light: #777; #Sass
用意されている変数($gray-lightなど)をSCSSで
使うには、bootstrap-sass
というgemを使う。
h2 {
color: $gray-light;
}
footer {
color: $gray-light;
}
実際にネストや変数を使ってcustom.scss
を書き直してみる
@import "bootstrap-sprockets";
@import "bootstrap";
/* mixins, variables, etc. */
$gray-medium-light: #eaeaea;
/* universal */
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: $gray-light;
}
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;
&:hover {
color: white;
text-decoration: none;
}
}
/* footer */
footer {
margin-top: 45px;
padding-top: 5px;
border-top: 1px solid $gray-medium-light;
color: $gray-light;
a {
color: $gray;
&:hover {
color: $gray-darker;
}
}
small {
float: left;
}
ul {
float: right;
list-style: none;
li {
float: left;
margin-left: 15px;
}
}
}
##レイアウトのリンク
footerパーシャルのレイアウトリンクを弄ってみる。
元々HTML記法の<a href="/static_pages/about">About</a>
が使われていたが、これはRails流ではないので以下のようにlink_to
メソッドで記述する。
<li><%= link_to "About", about_path %></li>
about_path
とは、名前付きルートと呼ばれるもので、これはルーティングで設定するが、後ほど解説する。
###Contactページ
まずはContactページを弄っていく。とりあえずテストから。
test "should get contact" do
get static_pages_contact_url
assert_response :success
assert_select "title", "Contact | Ruby on Rails Tutorial Sample App"
end
テストはRED
Contactページへのルートを追加。
get 'static_pages/contact'
さらにアクションを追加。
def contact
end
ビューも追加。
<% provide(:title, "Contact") %>
<h1>Contact</h1>
<p>
お問い合わせはこちら
</p>
再度テストしてGREENならOK。
$ rails t
###RailsのルートURL
現在のhomeのルーティングは
root 'static_pages#home'
rootメソッドを使って、ルートURLをコントローラのアクションに紐付けている。
このようなルーティングを定義することは、ブラウザからアクセスしやすくすることだけでなく、名前付きルート
を使ってURLを参照することができるようになる。
ルートURLにはroot_path
やroot_url
といったメソッドを通してURLを参照できる。
Railsチュートリアルでは基本的にroot_path
書式を使う。
リダイレクトの場合のみroot_url
書式を使う。(HTTPの標準としてリダイレクト時に完全なURLが要求される為)
ここでデフォルトのルーティングを名前付きルートに変更する。
例えば、
get `static_pages/help`
は
get '/help', to: 'static_pages#help'
という書き方に変更する。
このコードの意味は GETリクエストが/help
に送信されたときにStaticPagesコントローラのhelpアクション
を呼び出す。
また、ルートURLの時と同様にhelp_path
やhelp_url
といった名前付きルートも使えるようになる。
help_path -> '/help'
help_url -> 'http://www.example.com/help'
このように考えて、ルーティングを変更してみる。
Rails.application.routes.draw do
root 'static_pages#home'
get '/help', to: 'static_pages#help'
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
end
以前あったstatic_pages/home
は削除している。
今後は常にroot_path
またはroot_url
を使って行く。
ルーティングを変更したのでテストもroot_pathに変更する。
test "should get home" do
get root_path
assert_response :success
assert_select "title", "Ruby on Rails Tutorial Sample App"
end
test "should get help" do
get help_path
assert_response :success
assert_select "title", "Help | Ruby on Rails Tutorial Sample App"
end
test "should get about" do
get about_path
assert_response :success
assert_select "title", "About | Ruby on Rails Tutorial Sample App"
end
test "should get contact" do
get contact_path
assert_response :success
assert_select "title", "Contact | Ruby on Rails Tutorial Sample App"
end
テストを走らせてGREENであれば成功。
$ rails t
4 tests, 8 assertions, 0 failures, 0 errors, 0 skips
ここで演習をやってみる。
1:helpルーティングにas:
オプションで名前付きルートをhelf
に変更してみる。
get '/help', to: 'static_pages#help', as: 'helf'
2:この状態でtestを走らせると、REDになることを確認。
$ rails t
4 tests, 6 assertions, 0 failures, 1 errors, 0 skips
テストを修正しGREENに。
test "should get help" do
get helf_path
$ rails t
4 tests, 8 assertions, 0 failures, 0 errors, 0 skips
3:エディタのUndo機能を使って元に戻す
コマンドで戻せばOK
###名前付きルート
ルーティングでルートURLを定義したことにより、レイアウト内で名前付きルートが使えるようになった
実際にlink_to
メソッドで使ってみる。2番目の引数をいじる。
<%= link_to "sample app", root_path, id: "logo" %>
<nav>
<ul class="nav navbar-nav navbar-right">
<li><%= link_to "Home", root_path %></li>
<li><%= link_to "Help", help_path %></li>
<li><%= link_to "Log in", '#' %></li>
</ul>
footerパーシャルもリンクを変更。
<li><%= link_to "About", about_path %></li>
<li><%= link_to "Contact", contact_path %></li>
実際にクリックしてリンクに飛べるか確認。
演習
1:helfルーティングを作成し、レイアウトのリンクを更新してみる。
2:Undo機能で元に戻す
###リンクのテスト
先ほど貼ったリンクをテストする。
今回は今までの単体テストとは違い、統合テストを行う。
まずはテスト用のテンプレートを生成。
$ rails g integration_test site_layout
Running via Spring preloader in process 4732
invoke test_unit
create test/integration/site_layout_test.rb
ここで、integration_test
と言うのは統合テストのことである点に注目。
その後ろにsite_layout
というテンプレートを生成している。
今回のテストの目的は、アプリケーションのHTML構造を調べて、レイアウトの各リンクが正しく動くかどうかチェックすること
- ルートURL(Homeページ)にGETリクエストを送る。
- 正しいページテンプレートが描画されているかどうか確かめる。
- Home,Help,About,Contactの各ページへのリンクが正しく動くか確かめる。
Railsの統合テストでは、上の三つのステップをコードに落とし込んで行く
これを確認するために、assert_template
メソッドを使ってHomeページ
が正しいビューを描画しているかどうか確かめる。
require 'test_helper'
class SiteLayoutTest < ActionDispatch::IntegrationTest
# test "the truth" do
# assert true
# end
test "layout links" do
get root_path
assert_template 'static_pages/home'
assert_select "a[href=?]", root_path, count: 2
assert_select "a[href=?]", help_path
assert_select "a[href=?]", about_path
assert_select "a[href=?]", contact_path
end
end
ここではassert_select
メソッドの高度なオプションを使っている。
assert_select "a[href=?]", about_path
このコードでは、?
部分を自動的にabout_path
に置換している。
この時、about_path
内に特殊記号があればエスケープ処理される。
これにより、次のようなHTMLがあるかどうかをチェックすることができる。
<a href="/about">...</a>
そして、ルートURLへのリンクは二つあるので、root_pathへの確認では
assert_select "a[href=?]", root_path, count: 2
とcount: 2
で二つのカウントを取る(Homeページのリンクの個数を調べる)
assert_selectには様々な指定方法がある。
ここでは、頻繁に使われる一部のコードを紹介する。
Code マッチするHTML
assert_select "div" <div>foobar</div>
assert_select "div", "foobar" <div>foobar</div>
assert_select "div.nav" <div class="nav">foobar</div>
assert_select "div#profile" <div id="profile">foobar</div>
assert_select "div[name=yo]" <div name="yo">hey</div>
assert_select "a[href=?]", ’/’, count: 1 <a href="/">foo</a>
assert_select "a[href=?]", ’/’, text: "foo" <a href="/">foo</a>
表 5.2: assert_selectのいくつかの使用例
統合テストを実行するには次のようなRakeタスクを実行する
$ rails test:integration
1 tests, 5 assertions, 0 failures, 0 errors, 0 skips
つまり、`integration'ディレクトリ下のテストファイルの検証を行い、5アサーションが通りましたよという意味。
今度は全てのテストを走らせて、GREENになるかどうか確かめる。
$ rails t
5 tests, 13 assertions, 0 failures, 0 errors, 0 skips
5つのテストを検証し、13個のアサーションが通った模様。
演習
1:footerパーシャルのabout_path
をcontact_path
に変更し、テストが正しくエラーを捕まえるか確認。
5 tests, 12 assertions, 1 failures, 0 errors, 0 skips
2:Applicationヘルパーで使っているfull_title
ヘルパーをtest環境でも使えるようにする。
とりあえずtest_helper.rb
に以下を追記
class ActiveSupport::TestCase
fixtures :all
include ApplicationHelper
test環境でもアプリケーションヘルパーを使えるようにした。
get contact_path
assert_select "title", full_title("Contact")
test環境でfull_titleヘルパーを使う。
さらに、Applicationヘルパーをテストするファイルを作成する
require 'test_helper'
class ApplicationHelperTest < ActionView::TestCase
test "full title helper" do
assert_equal full_title, "Ruby on Rails Tutorial Sample App"
assert_equal full_title("Help"),"Help | Ruby on Rails Tutorial Sample App"
end
end
こうすることでbase_title
の誤字を発見できるようになる。
assert_equalでfull_titleと""の文字列が正しいかどうか検証している。
testを走らせる。
$ rails t
1 tests, 2 assertions, 0 failures, 0 errors, 0 skips
##ユーザー登録
ここからユーザー登録機能を設計する為のコントローラを作成する。
$ rails g controller Users new
Running via Spring preloader in process 9035
create app/controllers/users_controller.rb
route get 'users/new'
invoke erb
create app/views/users
create app/views/users/new.html.erb
invoke test_unit
create test/controllers/users_controller_test.rb
invoke helper
create app/helpers/users_helper.rb
invoke test_unit
invoke assets
invoke coffee
create app/assets/javascripts/users.coffee
invoke scss
create app/assets/stylesheets/users.scss
Users
コントローラは新規ユーザー作成のコントローラ、という意味である。(RESTアーキテクチャの規約に従う)
さらに、初期設定でnew
アクションを追加しておく。
この時、スタブのユーザービューも作成されている。
作成されたのを確認したら、とりあえずテストを走らせてみる。
$ rails t
1 tests, 1 assertions, 0 failures, 0 errors, 0 skips
OK。
演習
1:getレスポンスをsignup_pathに変更
get signup_path
2:テストがREDになったのを確認。
$ rails t
1 tests, 0 assertions, 0 failures, 1 errors, 0 skips
これは後signup_pathを作成するので今はOK。
###ユーザー登録用URL
ここで、先ほど設定したsignup_path
が通るように、ルーティングに/signup
を設定する。
get '/signup', to: 'users#new'
これでテストを走らせる。
$ rails t
1 tests, 6 assertions, 0 failures, 0 errors, 0 skips
OK。
あとはhomeぺージにsignupへのリンクを名前付きルートで貼る。
<%= link_to "Sign up now!", signup_path, class: "btn btn-lg btn-primary" %>
あとはsignupページ用のカスタムスタブのビューに以下を追加。
<% provide(:title, 'Sign up') %>
<h1>新規登録</h1>
<p>ユーザー登録はこちらからできまっせ〜</p>
このビューはルーティングで指定している通り、signup_path
のビューなので注意。
あとはrails sでSing up now
ボタンをクリックしてsignup
に飛べるか確認してみる。
演習
1:動作確認済み
2:signup
ルートをコメントアウトしてテストがREDになるか確認
*signup_pathを取得できないのでREDになる
3:統合テストにsignupページにアクセスするコードを追加
get signup_path
assert_select "title", full_title("Sign up")
テストを走らせる。
$ rails test:integration
1 tests, 7 assertions, 0 failures, 0 errors, 0 skips
OK。
##Git Heroku
いつも通りGitを使う。masterブランチにマージ。
$ git add -A
$ git commit -m "Finish layout and routes"
$ git checkout master
$ git merge filling-in-layout
テストを走らせる。
$ rails t
7 tests, 18 assertions, 0 failures, 0 errors, 0 skips
問題なければBitbucketにプッシュ。Herokuへデプロイ
$ git push
$ git push heroku
ここでherokuの本番環境で起動しなかった為、マイグレーションを起動させてみる。
heroku run rake db:migrate
これでOK。
#単語集
- Bootstrap
Twitter社が開発したオープンソースのWebデザインフレームワーク。
Webデザインを効率よく書けるツールで、フロントエンド周りのコーティングが苦手なエンジニアでも整ったページが作れる。
- class
CSSでスタイルを指定する時の印。classはHTMLページで何度でも使える。
- id
一部分にスタイルを指定したい場合に付ける印。idはHTMLページで一度しか使えない。
- image_tag
イメージタグを生成する。
書き方
image_tag(画像ファイルへのパス,[,(オプション or HTMLオプション)])
- alt
画像が表示されない場合にこの部分が表示される。
また、視覚障害者が使うスクリーンリーダーでは、この属性が読み上げられ、そこに画像があることが示される。
- link_to
Railsのリンクメソッド。
書き方
link_to ("画像ディレクトリの場所","画像クリック時のURL")
- レスポンシブデザイン
スマホでもタブレットでもPCでもWebページが綺麗に閲覧できることを目指したWebデザイン手法。
- タイポグラフィ
テキストや画像の配置を整える技法のこと。Webデザインには必須。
- em
文字のサイズを1とする単位のこと。
- shim
既存のコードの動作を修正する為に使用されるコード。
- render
指定したRHTMLを返す。Railsヘルパーの呼び出しに使う。
書き方
<%= render '相対パス' %>
- アセットパイプライン
CSS,JavaScript,画像などを一まとまりとして考え、生産性と管理を大幅に強化する機能。
- CoffeeScript
プログラミング言語。書いたコードがJavaScriptのコードに変換されるが、JavaScriptより簡単に書けるのが特徴。
- root_path
名前付きルートのメソッドで、ルートURL以下の文字列を返す
例
root_path -> '/'
- root_url
名前付きルートのメソッドで、完全なURLの文字列を返す
例
root_url -> 'http://www.example.com/'
- as
名前付きルートを変更するオプション。
as: 変更するルート名
で使うことができる
- 統合テスト
システム開発に置けるプログラムの検証作業の中でも、手続きや関数と行った個々の機能を統合させ、
うまく連携・動作しているかを確認するテストのこと。
統合テストで確認される点
- 個々の機能を果たす為のプログラムモジュールを組み合わせて、データの受け渡しがうまく行われているか
- コードの記述様式は揃っているか
- データを授受するタイミングはずれていないか
- Rakeタスク
Rubyで処理内容を定義できるビルドツールのこと。
- assert_equal
expected == actualがtrueであるかどうかを確かめるアサーション。
- スタブ
下位モジュールができるまでに使われる代用品のこと(要はテスト用の代役である)