Ruby on Rails チュートリアル

実例を使ってRailsを学ぼう

Michael Hartl (マイケル・ハートル)

第4版 目次

推薦の言葉

私が前にいた会社 (CD Baby) は、かなり早い段階でRuby on Railsに乗り換えたのですが、またPHPに戻ってしまいました (詳細は私の名前をGoogleで検索してみてください)。そんな私ですが、Michael Hartl 氏の本を強く勧められたので、その本を使ってもう一度試してみた結果、今度は無事に Rails に乗り換えることができました。それがこの Ruby on Rails チュートリアルという本です。

私は多くの Rails 関連の本を参考にしてきましたが、真の決定版と呼べるものは本書をおいて他にありません。本書では、あらゆる手順が「Rails 流」で行われています。最初のうちは慣れるまでに時間がかかりましたが、この本を終えた今、ついにこれこそが自然な方式だと感じられるまでになりました。また、本書は Rails 関連の本の中で唯一、多くのプロが推奨するテスト駆動開発 (TDD: Test Driven Development) を、全編を通して実践しています。実例を使ってここまで分かりやすく解説された本は、本書が初めてでしょう。極めつけは、Git や GitHub、Heroku の実例に含めている点です。このような、実際の開発現場で使わているツールもチュートリアルに含まれているため、読者は、まるで実際のプロジェクトの開発プロセスを体験しているかのような感覚が得られるはずです。それでいて、それぞれの実例が独立したセクションになっているのではなく、そのどれもがチュートリアルの内容と見事に一体化しています。

本書は、筋道だった一本道の物語のようになっています。私自身、章の終わりにある練習問題もやりながら、この Rails チュートリアルを3日間かけて一気に読破しました1。最初から最後まで、途中を飛ばさずにやるのが一番効果的で有益な読み方です。ぜひやってみてください。

それでは、楽しんでお読みください!

Derek Sivers (sivers.org) CD Baby 創業者

(訳注: たった3分のTEDの動画「社会運動をどうやって起こすか」を観たことがある方もいるのではないでしょうか。その方からの推薦の言葉です。)

謝辞

Ruby on Rails チュートリアルは、私の以前の著書「RailsSpace」と、その時の共著者 Aurelius Prochazka から多くを参考にさせてもらっています。Aure には、協力と本書への支援も含め、感謝したいと思います。また、RailsSpaceRails チュートリアルの編集を担当した Debra Williams Cauley 氏にも謝意を表したく思います。彼女が野球の試合に連れて行ってくれる限り、私は本を書き続けるでしょう。

私にインスピレーションと知識を与えてくれた Rubyist の方々にも感謝したいと思います: David Heinemeier Hansson, Yehuda Katz, Carl Lerche, Jeremy Kemper, Xavier Noria, Ryan Bates, Geoffrey Grosenbach, Peter Cooper, Matt Aimonetti, Mark Bates, Gregg Pollack, Wayne E. Seguin, Amy Hoy, Dave Chelimsky, Pat Maddox, Tom Preston-Werner, Chris Wanstrath, Chad Fowler, Josh Susser, Obie Fernandez, Ian McFarland, Steven Bristol, Pratik Naik, Sarah Mei, Sarah Allen, Wolfram Arnold, Alex Chaffee, Giles Bowkett, Evan Dorn, Long Nguyen, James Lindenbaum, Adam Wiggins, Tikhon Bernstam, Ron Evans, Wyatt Greene, Miles Forrest, Sandi Metz, Ryan Davis, Aaron Patterson, Pivotal Labs の方々、Heroku の方々、thoughtbot の方々、そして GitHub の方々、ありがとうございました。最後に、ここに書ききれないほど多くの読者からバグ報告や提案を頂きました。ご協力いただいた皆様のおかげで、本書の完成度をとことんまで高めることができました。

丁寧なレビュー、技術的なフィードバック、そして役立つ提案をしてくれた Andrew Thai に感謝します。また、Learn Enough to Be Dangerous の共同創業者である Nick Merwin と Lee Donahoe、日々のチュートリアルの制作をサポートしてくれてありがとう。

最後に、たくさんの読者の皆さん、そして、ここに挙げきれないほど多いコントリビューターのみんな、バグ報告や提案をしてくれてありがとう。彼ら/彼女らの多くの手助けに、最高の感謝を。

著者

マイケル・ハートル (Michael Hartl)Ruby on Rails Tutorial という、Web 開発を学ぶときによく参考にされる本の著者です。 また、Learn Enough to Be Dangerous (learnenough.com) 教育系ウェブサイトの創業者でもあります。 以前は、(今ではすっかり古くなってしまいましたが)「RailsSpace」という本の執筆および開発に携わったり、また、 一時人気を博した Ruby on Rails ベースのSNSプラットフォーム「Insoshi」の開発にも携わっていました。 2011年には、Rails コミュニティへの高い貢献が認められて、Ruby Hero Award を受賞しました。

ハーバード大学卒業後、カリフォルニア工科大学物理学博士号を取得。シリコンバレーの有名な起業プログラム Y Combinator の卒業生でもあります。

  1. 3日間で読破できる人は例外です! 実際には数週間〜数ヶ月をかけて読むのが一般的です。 

第5章レイアウトを作成する

4の簡単なRubyツアーでは、サンプルアプリケーションにアプリケーションスタイルシートを含める方法を学びました (4.1)。しかし4.3.4で指摘したとおり、このスタイルシートはまだ空のままです。 この章では、アプリケーションにBootstrapフレームワークを組み込み、そして、カスタムスタイルを追加します1。また、これまで作成したページ (HomeやAboutなど) へのリンクをレイアウトに追加します (5.1)。その途中で、パーシャル、Railsのルーティング、Asset Pipelineについて学び、さらにSassについても紹介します(5.2)。章の最後に、ユーザーをサイトにログインさせるための重要な一歩を踏み出します (5.4)。

本章では、サンプルアプリケーションにレイアウトを追加したり、修正したりといった部分に注力していきます。また、レイアウトについてはテスト駆動開発で進めたり、全くテストを書かない箇所もあります (テストを書くときと書かないときのガイドラインについてはコラム 3.3で解説します)。このため、本章ではテキストエディタによる修正とブラウザによる確認がほとんどになります。テスト駆動開発で進める唯一の箇所は、5.3.1のContactページを追加する箇所のみです。最後に、新しいテスト手法「 統合テスト (Integration Test)」について紹介します (5.3.4)。統合テストを使って、最終的なレイアウトやリンクが正しいかどうかをチェックします。

5.1 構造を追加する

RailsチュートリアルはWeb開発のための本であり、Webデザインの本ではありませんが、だからといって何のスタイルもない寒々しい外観のアプリケーションでいつまでも作業を続けていると憂鬱になってしまいます。そこでこの章では、レイアウトにいくつかの構造とCSSを与えて、最小限のスタイルを追加します。カスタムCSSルールの他に、Twitter社によるオープンソースのWebデザインフレームワークとして公開しているBootstrapも利用します。また、コードそのものにもスタイルを与えます。つまり、散らかり始めたレイアウトのコードを、パーシャル (Partial) 機能を使って整えていくということです。

Webアプリケーションを作成するときに、ユーザーインターフェイスの概要をできるだけ早いうちに把握しておくことがしばしば有用です。そこで本書では、モックアップ (Webの文脈ではよくワイヤーフレームと呼ばれます) という、実装後のアプリケーションの外観をスケッチして使っていきます2。また本章では、主に3.2で紹介したサイトロゴ、ナビゲーションヘッダー、サイトフッターを含む静的ページを開発します。 これらのページの中で最も重要な、Homeページのモックアップを図 5.1に示します。モックアップに基いて作成した最終結果は図 5.9で確認することができます。両者を見比べると、細部が若干異なることに気が付くでしょう (例えば、実際には最後にRailsのロゴをページに追加します)。しかしモックアップは正確である必要はありませんので、これで十分です。

images/figures/home_page_mockup_3rd_edition
図 5.1: サンプルアプリケーションのHomeページのモックアップ

Gitでバージョン管理をしているのであれば、これまでと同様、この時点で新しいブランチを作成するのがよいでしょう。

$ git checkout -b filling-in-layout

5.1.1 ナビゲーション

第一段階として、サンプルアプリケーションにリンクとスタイルを追加するために、サイトのレイアウトファイルapplication.html.erb (リスト 4.3) にHTML構造を追加し、レイアウトファイルを更新します。この更新には、領域 (divタグ) の追加、CSSクラスの追加、サイトナビゲーションの起点となる領域の追加も含まれます。 完全なファイルをリスト 5.1に示します。続いて、これを構成している多くの部品について解説します。 表示結果を今すぐ確認したいのであれば、図 5.2で確認できます (注:この時点ではわざわざ見に行くほどの仕上がりではありませんが)。

リスト 5.1: 構造を追加したWebサイトのレイアウト app/views/layouts/application.html.erb
<!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' %>
    <!--[if lt 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>

それでは、リスト 5.1の新しい要素を上から順に見ていきましょう。3.4.1でも簡単に説明しましたが、RailsはデフォルトでHTML5を使います (<!DOCTYPE html>と書いてHTML5であることを宣言します)。ただHTML5は比較的新しく、一部のブラウザ (特に旧式のInternet Explorer) ではHTML5のサポートが不完全である場合があります。そのため、次のようなJavaScriptのコード (通称: HTML5 shim (or shiv))3を使ってこの問題を回避します。

<!--[if lt IE 9]>
  <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/r29/html5.min.js">
  </script>
<![endif]-->

上のコードには、次のような奇妙な構文が含まれています。

<!--[if lt IE 9]>

これは、Microsoft Internet Explorer (IE) のバージョンが9より小さい場合 (if lt IE 9) にのみ、囲まれている行を実行します。 この風変わりな文法 [if lt IE 9] は、Railsの一部ではありません。これは実は、条件付きコメントと呼ばれるもので、今回のような状況のためにInternet Explorerで特別にサポートされています。 これにより、Firefox、Chrome、Safariなどの他のブラウザに影響を与えずに、IEのバージョンが9未満の場合にのみHTML5 shimをインクルードすることができるため、非常に好都合です。

それに続くセクションには、サイトのロゴを表示するheader、(divタグによる) いくつかの領域、ナビゲーションリンクのリストがあります。

<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>

headerタグは、ページの上部に来るべき要素を表します。このheaderタグには、navbarnavbar-fixed-topnavbar-inverseという3つのCSSクラスがスペース区切りで与えられています4

<header class="navbar navbar-fixed-top navbar-inverse">

すべてのHTML要素には、クラスとidの両方を指定することができます。これらは単なるラベルで、CSSでスタイルを指定するときに便利です (5.1.2)。 クラスとidの主な違いは、クラスはページの中で何度でも使用できるのに対し、idは一度しか使用することができない点です。 今回の場合、すべてのnavbarクラスには、5.1.2でインストールするBootstrapフレームワークによって特別な意味が与えられます。

headerタグの内側には2つのdivタグがあります。

<div class="container">

divタグは一般的な表示領域を表し、ドキュメントを別々のパーツに分ける以外のことはしません。 古いスタイルのHTMLでは、divタグはサイトのほぼすべての領域に使用されますが、HTML5では多くのアプリケーションに共通の領域で使用するheader要素、nav要素、section要素が追加されています。 この場合、divタグにもCSSクラス (container) が与えられています。 headerタグのクラスと同様に、このクラスもBootstrapにおいて特別な意味を持っています。

divに続いて、埋め込みRubyコードが出現します。

<%= 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>

ここでは、リンクを生成するために、Railsヘルパーのlink_toを使います (3.2.2で見たアンカータグaが最終的に生成されます)。link_toの第1引数はリンクテキスト、第2引数はURLです。このURLは5.3.3名前付きルート (Named Routes) に置き換えますが、今はWebデザインで一般に使われるスタブ用の (とりあえずのダミーとして使われる) URL「’#’」を置いておきます。第3引数はオプションハッシュで、この場合はサンプルアプリのリンクでCSS id logoを指定しています(他の3つのリンクにはオプションハッシュが指定されていませんが、必須ではないので構いません)。Railsヘルパーは、このようにオプションのハッシュを取ることがよくあり、これによりRailsのコードから離れることなく任意のHTMLオプションを柔軟に追加することができます。

divの内側の2番目の要素は、リストアイテムタグli順不同リストタグulによって作られた、ナビゲーションリンクのリストです。

<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>

正確にはここでは不要なのですが、navタグには「その内側がナビゲーションリンクである」という意図を明示的に伝える役割があります。 さらに、ulタグに付与されているnavnavbar-navnavbar-rightクラスもBootstrapにおいて特別な意味を持ちます。したがって、5.1.2でBootstrapのCSSを追加したときに、これらのスタイルも自動的に適用されます。 ブラウザからソースを見ることで確認ができますが、Railsが埋め込みRubyを評価し、レイアウトを描画すると、上のリストは次のように置き換わります5

<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>

これがブラウザに返されるHTMLになります。

レイアウトの最後の部分は、メインコンテンツ用のdivです。

<div class="container">
  <%= yield %>
</div>

上と同様、containerクラスもBootstrapにおいて特別な意味を持ちます。 3.4.3で学んだように、yieldメソッドはWebサイトのレイアウトにページごとの内容を挿入します。

5.1.3で追加するサイトフッターを除いて、これでレイアウトは完成しました。Homeページへアクセスして表示結果を確認することができます。 今後のスタイル要素を利用するために、home.html.erbビューに特別な要素をいくつか追加します (リスト 5.2)。

リスト 5.2: サインアップページへのリンクがあるHomeページ app/views/static_pages/home.html.erb
<div class="center jumbotron">
  <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-lg btn-primary" %>
</div>

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

7でサイトにユーザーを追加するときに備えて、最初のlink_toで次のような仮のリンクを生成します。

<a href="#" class="btn btn-lg btn-primary">Sign up now!</a>

上で挙げたdivタグのCSSクラスjumbotronや、signupボタンのbtnクラス、btn-lgクラス、btn-primaryクラスはすべて、Bootstrapにおいて特別な意味を持ちます。

2番目のlink_toでは、引数として画像ファイルのパスと任意のオプションハッシュをとるimage_tagヘルパーの能力が示されています。シンボルを使用して、この場合はalt属性を設定しています。 画像を表示するためには、rails.pngというRailsのロゴ画像ファイルを加える必要があります。Ruby on Rails公式ページの http://railstutorial.jp/rails.png から画像をダウンロードして、app/assets/images/ディレクトリにおいてください6。Cloud IDEやUnix系のOS (Max OS Xなど) を使っている場合は、次のようにcurlコマンドで簡単に取得することができます (リスト 5.3)。(curlコマンドの詳細についてはCommand Line Tutorial (英語) をご覧ください)

リスト 5.3: 画像をダウンロードする
$ curl -o app/assets/images/rails.png -OL railstutorial.jp/rails.png

リスト 5.2image_tagヘルパーを使っているので、Railsは該当する画像ファイルを、アセットパイプラインを通してapp/assets/images/ディレクトリの中から探してくれます (アセットパイプラインについては5.2で説明します)。

さて、これで準備は完了です。環境によっては、ここで一度Railsサーバーを再起動する必要がある場合もあるので、必要に応じて (コラム 1.1) 再起動を試してみてください。うまく行くと、次の図 5.2のような結果になるはずです。

images/figures/layout_no_logo_or_custom_css_bootstrap_3rd_edition
図 5.2: カスタムCSSを使っていないHomeページ

image_tagの効果を確かめるために、ブラウザから生成されたHTMLを見てみましょう7

<img alt="Rails logo" src="/assets/rails-9308b8f92fea4c19a3a0d8385b494526.png" />

ファイル名が重ならないようにするために、9308b8f92fea4c19a3a0d8385b494526という文字列 (実際の文字列はシステムごとに異なります) をRailsが追加していることがわかります。これは、たとえば画像ファイルを新しい画像に更新したときに、ブラウザ内に保存されたキャッシュに意図的にヒットさせないようにするための仕組みです。 また、src属性には "images" というディレクトリ名が含まれていないことにも注目してください。これはassetsディレクトリ内の他のディレクトリ (imagesやjavascripts、stylesheetsなど) も同様です。これは高速化のための仕組みで、Railsはassetsディレクトリ直下の画像をapp/assets/imagesディレクトリにある画像と紐付けています。これにより、ブラウザから見るとすべてのファイルが同じディレクトリにあるように見えるようになります。そして、このようなフラットなディレクトリ構成を採っていると、ファイルをより高速にブラウザに渡すことができるようになります。最後に、alt属性は、画像がない場合に代わりに表示される文字列です。たとえば視覚障害のあるユーザーが使用するスクリーンリーダーでは、ここの属性が読み上げられて、そこに画像があることが示されます。

いよいよ、ここまでの苦労の成果を確認する準備ができました (図 5.2)。思っていたよりもみすぼらしいでしょうか。そうかもしれません。しかし、HTML要素に実用的なクラスを与えるという良い仕事ができたのも確かです。さらに、クラスを与えたこの段階で、CSSを使用してサイトにスタイルを与えることができたのは、タイミングとして非常に適切であると思います。

演習

  1. Webページと言ったらネコ画像、というぐらいにはWebにはネコ画像が溢れていますよね。リスト 5.4のコマンドを使って、図 5.3のネコ画像をダウンロードしてきましょう8
  2. mvコマンドを使って、ダウンロードしたkitten.jpgファイルを適切なアセットディレクトリに移動してください (参考: 5.2.1)。
  3. image_tagを使って、kitten.jpg画像を表示してみてください (図 5.4)。
images/figures/kitten
図 5.3: Webで必須 (?) の子ネコ画像
リスト 5.4: ネコ画像をインターネットからダウンロードする
$ curl -OL cdn.learnenough.com/kitten.jpg
images/figures/kitten_on_home
図 5.4: 子ネコ画像をHomeページに表示させた結果

5.1.2 BootstrapとカスタムCSS

5.1.1では、多くのHTML要素にCSSクラスを関連付けました。こうしておくことで、CSSベースでレイアウトを構成する際に高い柔軟性を与えてくれます。5.1.1で述べたように、これらのクラスの多くは、Twitterが作成したフレームワークであるBootstrap特有のものです。Bootstrapを使用すると、洗練されたWebデザインとユーザーインターフェイス要素を簡単にHTML5アプリケーションに追加することができます。 この節では、サンプルアプリケーションにスタイルを追加するために、カスタムCSSルールとBootstrapを組み合わせて使用します。 注目すべき点は、Bootstrapを使うことでアプリケーションをレスポンシブデザイン (Responsive Design) にできるということです。これにより、どの端末でアプリケーションを閲覧しても、ある程度見栄えをよくすることができます。

最初に、リスト 5.5で示しているようにBootstrapを追加しましょう。これは、bootstrap-sass gemを使用してRailsアプリケーションに導入できます9。Bootstrapフレームワークでは、動的なスタイルシートを生成するためにLESS CSS言語を使用していますが、RailsのAsset Pipelineはデフォルトでは (LESSと非常によく似た) Sass言語をサポートします (5.2)。そのため、bootstrap-sassは、LESSをSassへ変換し、必要なBootstrapファイルを現在のアプリケーションですべて利用できるようにします10

リスト 5.5: Gemfilebootstrap-sassを追加する
source 'https://rubygems.org'

gem 'rails',          '5.0.3'
gem 'bootstrap-sass', '3.3.7'
.
.
.

いつものようにbundle installを実行して、Bootstrapをインストールします。

$ bundle install

ちなみに、rails generateコマンドを実行することでコントローラーごとに分けられたCSSファイルが自動的に生成されますが、これらのファイルを正しい順序で読み込ませるのは至難の技なので、本チュートリアルでは (簡潔のために) すべてのCSSを1つにまとめる方針を採っています。 カスタムCSSを動かすための最初の一歩は、カスタムCSSファイルを作ることです。

$ touch app/assets/stylesheets/custom.scss

(ここでは3.3.3 の途中で紹介した touch コマンドを使っていますが、ファイルが作成できるなら [新規ファイル作成] や他のコマンドでも問題ありません。) このディレクトリ名とファイル名は、どちらも重要です。 以下のディレクトリは、

app/assets/stylesheets/

Asset Pipeline (5.2)の一部であり、このディレクトリに置かれたスタイルシートはapplication.cssの一部としてWebサイトのレイアウトに読み込まれます。さらに、ファイル名のcustom.scssには.scssという拡張子も含まれています。この拡張子は「Sass (Sassy CSS)」と呼ばれるCSSを拡張した言語で、アセットパイプラインはこのファイルの拡張子を見て、Sassを処理できるようにしています (Sassは5.2.2まで登場しませんが、bootstrap-sass gemが動作するためのおまじないとして必要です)。

カスタムCSS用のファイルを作成したら、リスト 5.6のように@importを使って、Bootstrap (とそれに関連するSprockets) を読み込みます11

リスト 5.6: Bootstrap CSSを追加する app/assets/stylesheets/custom.scss
@import "bootstrap-sprockets";
@import "bootstrap";

リスト 5.6の2行では、Bootstrap CSSのフレームワークを導入しています。導入後、Webサーバを再起動させると、アプリケーションに反映させることができます。 (1.3.2で紹介したように、Ctrl-Cを押してWebサーバを停止させた後、rails serverコマンドを打ってWebサーバを起動してください)。うまくいけば図 5.5のような結果になります。さて、テキストの配置は今ひとつで、ロゴにはスタイルもありませんが、色使いとsignupボタンはなかなかよい感じになってきました。

images/figures/sample_app_only_bootstrap_3rd_edition
図 5.5: Bootstrap CSSとサンプルアプリケーション

次に、リスト 5.7に示したように、Webサイト全体にわたってレイアウトと個別のページにスタイルを与えるためのCSSを追加します。 テストの結果を図 5.6に示します。リスト 5.7には多数の記述ルールがあります。CSSの記述ルールを把握するためには、関心のある箇所をコメントアウトして表示を確認することをお勧めします。CSSでは /* … */ でコメントアウトできるので、調べてみたいコードをこれで囲い、表示がどのように変わるかを確認してみてください。

リスト 5.7: すべてのページに適用される共通のスタイルをCSSに追加する app/assets/stylesheets/custom.scss
@import "bootstrap-sprockets";
@import "bootstrap";

/* universal */

body {
  padding-top: 60px;
}

section {
  overflow: auto;
}

textarea {
  resize: vertical;
}

.center {
  text-align: center;
}

.center h1 {
  margin-bottom: 10px;
}
images/figures/sample_app_universal_3rd_edition
図 5.6: スペースや共通スタイルを追加した結果

リスト 5.7のCSSの形式は一貫しています。 CSSルールでは一般に、クラス、id、HTMLタグ、またはそれらの組み合わせ、のいずれかを指定します。そしてその後ろにスタイリングコマンドのリストを記述します。 たとえば、以下のコードでは、

body {
  padding-top: 60px;
}

ページ上部に60ピクセルの余白を追加します。 headerタグにnavbar-fixed-topクラスが与えられているので、これに従ってBootstrapはナビゲーションバーをページ上部に固定し、ナビゲーションバーの下に余白を置いて主要部分から分離します (デフォルトのnavbarの色がBootstrap 2.0から変更されたため、現在の淡色の代わりにダークな色調にしたい場合はnavbar-inverseクラスを使用する必要があります)。 また、このルールにある以下のCSSは、

.center {
  text-align: center;
}

centerクラスにtext-align: centerプロパティを関連付けています。 言い換えると、.center冒頭のドット.は、このルールがクラスに対してスタイルを適用することを示しています。なお、リスト 5.9に示したように、冒頭がポンド記号#で始まる場合は、そのルールがCSSのidに対してスタイルを適用することを示します。今回の場合、centerクラスに属している (divなどの) タグの内側にある要素が、すべて中央揃えになることを意味しています (リスト 5.2が実際の使用例です)。

Bootstrapには洗練されたタイポグラフィーを利用できるCSSルールがありますが、ここではさらに、リスト 5.8のようにカスタムCSSルールを追加し、テキストの見栄えを変えてみましょう。なお、今回追加するルールはHomeページのすべてで適用されるとは限りませんが、サンプルアプリケーションの他の場所でも使われます。リスト 5.8を反映した結果を、図 5.7で確認することができます。

リスト 5.8: 洗練されたタイポグラフィーを利用するためのCSSを追加する app/assets/stylesheets/custom.scss
@import "bootstrap-sprockets";
@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: #777;
}

p {
  font-size: 1.1em;
  line-height: 1.7em;
}
images/figures/sample_app_typography_3rd_edition
図 5.7: タイポグラフィースタイルを追加する

最後に、いくつかのルールをサイトロゴに追加します。このサイトロゴは「sample app」だけが表示されているシンプルなものです。 リスト 5.9のCSSは、テキストを大文字に変換し、サイズ、色、配置を変更します (サイトロゴがページで一度しか使用されないことを前提としてCSS idを使用していますが、代わりにクラスを使用することもできます)。

リスト 5.9: サイトロゴにCSSを追加する app/assets/stylesheets/custom.scss
@import "bootstrap-sprockets";
@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;
}

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

上のコードのcolor: #fffは、ロゴの色を白に変更します。HTMLの色は、16進数 (基数が16) の3つの数値の組み合わせで表現され、赤、緑、青の三原色に (この順序で) コード化することができます。本来は#ffffffと書いて3色すべてを最大にする必要がありますが、上のコードでは#fffという#ffffffの短縮形を使っています。ちなみにCSS標準では、HTMLの色には別名も多数定義されています。例えば先ほどの#fffは、whiteと書くこともできます。話を戻して、リスト 5.9のCSSが反映されると、図 5.8のようになっていれば成功です。

演習

  1. リスト 5.10を参考にして、5.1.1.1で使ったネコ画像をコメントアウトしてみてください。また、ブラウザのHTMLインスペクタ機能を使って、コメントアウトするとHTMLのソースからも消えていることを確認してみてください。
  2. リスト 5.11のコードをcustom.scssに追加し、すべての画像を非表示にしてみてください。うまくいけば、Railsのロゴ画像がHomeページから消えるはずです。先ほどと同様にインスペクタ機能を使って、今度はHTMLのソースコードは残ったままで、画像だけが表示されなくなっていることを確認してみてください。
リスト 5.10: 埋め込みRubyのコードをコメントアウトする
<%#= image_tag("kitten.jpg", alt: "Kitten") %>
リスト 5.11: すべての画像を非表示にするCSS
img {
  display: none;
}

5.1.3 パーシャル (partial)

リスト 5.1のレイアウトはその目的を果たしていますが、少々散らかっています。 HTML shimは、それだけで3行も占有し、風変わりなIE特有の文法を使用しているので、これをうまく隠すことができたらどんなによいでしょう。 また、HTMLヘッダーは論理的な単位を形成するため、一箇所にまとめる必要もあります。 Railsでは、パーシャル (partial) と呼ばれる機能を使用してこれを実現することができます。 最初に、パーシャルを定義するとレイアウトがどのように変わるかを見てみましょう (リスト 5.12)。

リスト 5.12: レイアウトにshimとheaderのパーシャルを追加する app/views/layouts/application.html.erb
<!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>

リスト 5.12では、以下のようにrenderと呼ばれるRailsヘルパー呼び出しだけを使って、HTML shimのスタイルシート行を置換しています。

<%= render 'layouts/shim' %>

この行では、app/views/layouts/_shim.html.erbというファイルを探してその内容を評価し、結果をビューに挿入しています12 (<%= ... %> は、テンプレート内でRubyの式を評価するための埋め込みRuby記法であることを思い出してください。評価した結果がテンプレートに挿入されます)。ファイル名 _shim.html.erb の先頭にあるアンダースコアに注目してください。このアンダースコアは、パーシャルで使用する普遍的な命名規約であり、また、一目見ただけでディレクトリ中のすべてのパーシャルを識別することが可能になります。

もちろん、パーシャルが動作するためには、それに対応するファイルとコンテンツを記述しなければなりません。このshimパーシャルの場合は、リスト 5.1のわずか3行のshimコードだけです。作成したコードをリスト 5.13に示します。

リスト 5.13: HTML shim用のパーシャル app/views/layouts/_shim.html.erb
<!--[if lt IE 9]>
  <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/r29/html5.min.js">
  </script>
<![endif]-->

同様に、ヘッダーの情報もリスト 5.14のパーシャルに移動し、renderを呼び出してレイアウトに挿入することができます。 (パーシャルでは、自動生成せずに、テキストエディタを使って手動で作成するのが一般的です。)

リスト 5.14: header用のパーシャル app/views/layouts/_header.html.erb
<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.html.erb で、layoutsディレクトリ (リスト 5.15) に置けばよいということが分かると思います13

ヘッダーの場合と同様に、フッターの中でもlink_toメソッドを使用して、AboutページとContactページへの内部リンクを追加してあります。ひとまず、リンク先のURLは’#’としておきます (headerタグと同様、footerタグもHTML5で新たに追加された要素です)。

footerパーシャルは、スタイルシートやheaderパーシャルのときと同じ方法でレイアウト中に追加できます (リスト 5.16)。

そのまま実際にfooterを表示してみるとどうにも見苦しいので、リスト 5.17でスタイルを若干追加しましょう。 スタイルを追加した結果を図 5.9に示します。

演習

  1. Railsがデフォルトで生成するheadタグの部分を、リスト 5.18のようにrenderに置き換えてみてください。ヒント: 単純に削除してしまうと後でパーシャルを1から書き直す必要が出てくるので、削除する前にどこかに退避しておきましょう。
  2. リスト 5.18のようなパーシャルはまだ作っていないので、現時点ではテストは redになっているはずです。実際にテストを実行して確認してみましょう。
  3. layoutsディレクトリにheadタグ用のパーシャルを作成し、先ほど退避しておいたコードを書き込み、最後にテストが green に戻ることを確認しましょう。
リスト 5.18: Railsのデフォルトのheadタグをrenderに置き換える app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title><%= full_title(yield(:title)) %></title>
    <%= render 'layouts/rails_default' %>
    <%= render 'layouts/shim' %>
  </head>
  <body>
    <%= render 'layouts/header' %>
    <div class="container">
      <%= yield %>
      <%= render 'layouts/footer' %>
    </div>
  </body>
</html>

5.2 Sassとアセットパイプライン

最近のRailsに追加された機能の中で最も特筆すべき機能のひとつは、CSS、JavaScript、画像などの静的コンテンツの生産性と管理を大幅に強化する「アセットパイプライン (Asset Pipeline)」です。このセクションでは、アセットパイプラインの概要と、素晴らしいCSS生成ツールである「Sass」の使い方について説明します。

5.2.1 アセットパイプライン

Rails開発者の視点からは、アセットディレクトリ、マニフェストファイル、プリプロセッサエンジンという、3つの主要な機能が理解の対象となります14。では、それぞれを順に見ていきましょう。

アセットディレクトリ

Railsのアセットパイプラインでは、静的ファイルを目的別に分類する、標準的な3つのディレクトリが使用されています。

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

これらのディレクトリには、それぞれのアセットクラス用のサブディレクトリがあります。例えばapp/assetsの場合、次のような画像用、JavaScript用、CSS用のサブディレクトリがあります。

$ ls app/assets/
images/  javascripts/  stylesheets/

上記の説明から、5.1.2で取り上げたカスタムCSSが配置された場所と、その理由について理解することができると思います。つまり、custom.scssはサンプルアプリケーション固有のアセットなので、app/assets/stylesheetsに配置されていたのです。

マニフェストファイル

静的ファイル (アセット) を上記の場所へそれぞれ配置すれば、マニフェストファイルを使用して、それらをどのように1つのファイルにまとめるのかをRailsに指示することができます。なお、実際にアセットをまとめる処理を行うのはSprocketsというgemです。また、マニフェストファイルはCSSとJavaScriptには適用されますが、画像ファイルには適用されません。 1つの具体例として、アプリケーションのCSS用マニフェストファイルを見てみましょう (リスト 5.19)。

リスト 5.19: アプリケーション固有の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 bottom of the compiled file so the styles you add here take
 * precedence over styles defined in any styles defined in the other CSS/SCSS
 * files in this directory. It is generally better to create a new file per
 * style scope.
 *
 *= require_tree .
 *= require_self
 */

上の行で重要な部分は実はCSSコメントの中にあります。以下の行は、適切なファイルをインクルードするためにSprocketsによって使用されます。

/*
 .
 .
 .
 *= require_tree .
 *= require_self
*/

次の行は、

 *= require_tree .

app/assets/stylesheetsディレクトリ (サブディレクトリを含む) 中のすべてのCSSファイルが、アプリケーションCSSに含まれるようにします。また、次の行は、

 *= require_self

CSSの読み込みシーケンスの中で、application.css自身もインクルードすることを指定しています。

Railsには実用的なデフォルトのマニフェストファイルが付属しているので、Railsチュートリアルでは変更を加える必要がありませんが、もし必要な場合は、Railsガイドの「アセットパイプライン」で詳細な情報を参照できます。

プリプロセッサエンジン

必要なアセットをディレクトリに配置してまとめた後、Railsはさまざまなプリプロセッサエンジンを介してそれらを実行し、ブラウザに配信できるようにそれらをマニフェストファイルを用いて結合し、サイトテンプレート用に準備します。 Railsは、どのプリプロセッサを使用するかを、ファイル名の拡張子を使用して判断します。最も一般的な拡張子は、Sass用の.scss、CoffeeScript用の.coffee、埋め込みRuby (ERb) 用の.erbです。 3.4.3では最初にERbを、5.2.2ではSassをそれぞれ扱いました (なお本書では詳しく説明しませんが、CoffeeScriptはエレガントかつ簡潔な言語で、JavaScriptにコンパイルしてくれるJavaScriptの拡張言語です)。

プリプロセッサエンジンは、繋げて実行する (chain) ことができます。

foobar.js.coffee

上の拡張子の場合、CoffeeScriptプロセッサ経由で実行されます。

foobar.js.erb.coffee

上の拡張子の場合は、CoffeeScriptとERbの両方で実行されます (コードは右から左へと実行されますので、この例ではCoffeeScriptが最初に実行されます)。

本番環境での効率性

Asset Pipelineの最大のメリットの1つは、本番のアプリケーションで効率的になるように最適化されたアセットも自動的に生成されることです。 従来は、CSSとJavaScriptを整理するために、機能を個別のファイルに分割し、(インデントを多用して) 読みやすいフォーマットに整えていました。 これは、プログラマにとっては便利な方法ですが、本番環境にとっては非効率です。 それというのも、最小化されていないCSSやJavaScriptファイルを多数インクルードすると、ページの読み込み時間が著しく遅くなるからです (読み込み時間は、ユーザー体験の質に影響を与える重要な指標の1つです)。 Asset Pipelineを使うと、この「開発効率と読み込み時間のどちらを重視するか」という問題について悩む必要がなくなります。開発環境ではプログラマにとって読みやすいように整理しておき、本番環境ではAsset Pipelineを使ってファイルを最小化すればよいのです。 具体的には、Asset Pipelineがすべてのスタイルシートを1つのCSSファイル (application.css) にまとめ、すべてのJavaScriptファイルを1つのJSファイル (javascripts.js) にまとめてくれます。さらに、それらのファイルすべてに対して 不要な空白やインデントを取り除く処理を行い、ファイルサイズを最小化してくれます。 結果として、開発環境と本番環境という、2つの異なった状況に対してそれぞれ最高の環境を提供してくれます。

5.2.2 素晴らしい構文を備えたスタイルシート

Sass は、スタイルシートを記述するための言語であり、CSSに比べて多くの点が強化されています。 この節では、Sassが提供する2つの重要な機能、ネスト変数について説明します。 (3つ目の重要な機能であるミックスインについては、7.1.1で紹介します)。

5.1.2でも簡単に説明しましたが、SassはSCSSというフォーマットに対応しています (.scssという拡張子はSCSSであることを表します)。SCSSは厳密な意味で、CSS本体を抽象化したフォーマットです。つまり、SCSSはCSSに新しい機能を追加しただけで、全く新しい構文を定義したようなものではないということです15。このため、有効なCSSファイルは、すべてSCSSファイルとしても扱うことができ、既存の記法ルールを使用しているプロジェクトにとっても互換性のある便利なフォーマットになっています。 本書の例では、Bootstrapの恩恵を得るために、私達は最初からSCSSを使用しています。 Railsのアセットパイプラインは、.scssという拡張子を持つファイルをSassを使って自動的に処理してくれます。このため、custom.scssファイルはSassプリプロセッサによって前処理され、その後ブラウザへの配信に備えてパッケージ化されます。

ネスト

スタイルシート内に共通のパターンがある場合は、要素をネストさせることができます。 たとえば、リスト 5.7では、以下のように.center.center h1の両方に対してルールがあります。

.center {
  text-align: center;
}

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

上のルールは、Sassを使用して以下のように書き換えることができます。

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

上の例では、ネストの内側にあるh1というルールは、.centerのルールを継承しています。

今度は、もう少し異なるルールに対してネスト機能を使う例を見てみましょう。 リスト 5.9には次のコードがあります。

#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;
}

上のコードには#logoというidが2回使用されています。1回目はロゴ自身を定義するために、2回目はhover属性を定義するために使用されています (なおhover属性は、該当する要素の上にマウスポインタをかざしたときの表示を定義します)。2つ目のルールをネストするためには、親属性である#logoを参照する必要があります。このような場合、SCSSでは次のようにアンパーサンド&を使って実現できます。

#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に置き換えています。

これらのネスト機能は、フッターのCSSでも使用できます。リスト 5.17のコードは、SCSSを使用して次のように書き換えることができます。

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

リスト 5.17を手作業で変換してみることは、良い演習になります (実際に5.2.2.3でも取り入れてみました)。変換後にも、CSSが適切に動作していることを確認してみましょう。

変数

Sassでは、冗長なコードを削除し、より自由な表現を可能にするために、変数が定義できるようになっています。 たとえば、リスト 5.8リスト 5.17を見てみると、同じ色を繰り返し参照している箇所があります。

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

上のコードの#777は薄い灰色を指しています。Sassでは、このような値を変数として定義し、次のように変数名を与えることができます。

$light-gray: #777;

この機能を使用して、SCSSを以下のように書き直すことができます。

$light-gray: #777;
.
.
.
h2 {
  .
  .
  .
  color: $light-gray;
}
.
.
.
footer {
  .
  .
  .
  color: $light-gray;
}

$light-grayのような変数名は、#777のような値よりも分かりやすいので、たとえその変数が繰り返し使われないとしても、変数名を与えることは多くの場合有用です。 実際、Bootstrapフレームワークでは、多くの色に対して変数名を定義しています。定義されている変数はBootstrapページの「LESS変数一覧」で参照することができます。 このWebサイトでは、SassではなくLESSを使って変数が定義されていますが、bootstrap-sassというgemを使用すれば、Sassでも同様の変数が使えるようになります。 たとえば、LESSではアットマーク@を使用しているのに対して、Sassはドルマーク$を使っていることはすぐにわかります。話を戻して、Bootstrapの変数の一覧表を見ると、薄い灰色に対して次の変数名が与えられることに気が付きます。

 @gray-light: #777;

これはつまり、bootstrap-sassというgemを使えば、SCSSでも同様に$gray-lightという変数が使えることを意味しています。先ほど定義した$light-grayというカスタム変数の代わりに、用意された変数を使ってみましょう。

h2 {
  .
  .
  .
  color: $gray-light;
}
.
.
.
footer {
  .
  .
  .
  color: $gray-light;
}

今回取り上げたSassのネスト機能や変数機能を使ってSCSSファイルを全面的に書き直すと、リスト 5.20のようになります。 このリストでは、Sassの変数 (詳しくはBootstrap LESSの変数一覧を参照) や、組み込みの色変数 (たとえば#fffにはwhiteという変数) を使っています。footerタグのルールが、劇的に向上していることを確認してみてください。

リスト 5.20: ネストや変数を使って初期のSCSSファイルを書き直した結果 app/assets/stylesheets/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;
    }
  }
}

Sassを使ってスタイルシートをより簡単にする方法は他にもありますが、今回はその中でも最も重要な機能を使ってリスト 5.20を書き直しました。Sassを使うことによって、素晴らしいスタートを切ることができました。 Sassの詳細については、Sassの公式サイト (英語) を参照してください。

演習

  1. 5.2.2で提案したように、footerのCSSを手作業で変換してみましょう。具体的には、リスト 5.17の内容を1つずつ変換していき、リスト 5.20のようにしてみてください。

5.4 ユーザー登録: 最初のステップ

この節では、レイアウトとルーティングの取り組みにおける頂点として、ユーザー登録ページへのルーティングを作成します。そのために2番目のコントローラを作成することになります。 これは、Webサイトでユーザー登録を行えるようにするための最初の重要な一歩となります。次の一歩であるユーザーのモデリングは6で行い、7でユーザー登録が完成します。

5.4.1 Usersコントローラ

3.2で、最初のコントローラであるStaticPagesコントローラを作成しました。 今度は2番目のコントローラであるUsersコントローラを作成しましょう。 以前のときと同様に、generateを実行して、現時点での要求である新規ユーザー用のユーザー登録ページ (スタブ) を持つ、最も簡単なコントローラを作成します。Railsで好まれているRESTアーキテクチャの規約に従い、新規ユーザー用のアクションをnewとします。したがって、generate controllerの引数にnewを渡して、自動的にアクションを作成してみましょう。 変更の結果をリスト 5.38に示します。

リスト 5.38: Usersコントローラの生成 (newアクションを追加)
$ rails generate controller Users new
      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

リスト 5.38により、newアクションを持つUsersコントローラ(リスト 5.39)と、スタブのユーザービューを作成します(リスト 5.40)。このとき、新しいUserページ用の小さなテスト (リスト 5.41) も生成されていて、この時点ではパスするはずです。

リスト 5.39: newアクションを持つ最初のUsersコントローラ app/controllers/users_controller.rb
class UsersController < ApplicationController

  def new
  end
end
リスト 5.40: Users用の最初のnewアクション app/views/users/new.html.erb
<h1>Users#new</h1>
<p>Find me in app/views/users/new.html.erb</p>
リスト 5.41: Userページ用の最初のテスト green test/controllers/users_controller_test.rb
require 'test_helper'

class UsersControllerTest < ActionDispatch::IntegrationTest

  test "should get new" do
    get users_new_url
    assert_response :success
  end
end

この時点では、テストは greenになっているはずです。

リスト 5.42: green
$ rails test

演習

  1. 表 5.1を参考にしながらリスト 5.41を変更し、users_new_urlではなくsignup_pathを使えるようにしてみてください。
  2. 先ほどの変更を加えたことにより、テストが redになったことを確認してください。なお、この演習はテスト駆動開発 (コラム 3.3) で説明した red/green のリズムを作ることを目的としています。このテストは次の5.4.2greenになるよう修正します。

5.4.2 ユーザー登録用URL

5.4.1のコードにより、新規ユーザー用の動作するページが/users/new にできました。ここで表 5.1を思い出していただきたいのですが、URLは/users/newではなく表のとおりに/signupにしたいと思います。 リスト 5.27の例に従い、ユーザー登録URL用にget ’/signup’のルートを追加します (リスト 5.43)。

リスト 5.43: ユーザー登録ページのルート red config/routes.rb
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'
  get  '/signup',  to: 'users#new'
end

リスト 5.43の変更に合わせて、リスト 5.38で生成されたテストも修正していきましょう。 修正した結果をリスト 5.44に示します。

リスト 5.44: Usersコントローラのテストで名前付きルートを使うようにする green test/controllers/users_controller_test.rb
require 'test_helper'

class UsersControllerTest < ActionDispatch::IntegrationTest

  test "should get new" do
    get signup_path
    assert_response :success
  end
end

次に、新しく定義された名前付きルートを使って、Homeページのボタンに適切なリンクを追加します。他のルートと同様、get ’/signup’と記述したことでsignup_pathという名前付きルートができ、それをリスト 5.45で使用します。なお、signupページへのテストは演習に回すことにします (5.3.2.1)。

最後に、signupページ用のカスタムスタブ (stub) のビューを追加します (5.46)。

リスト 5.46: 最初のユーザー登録ページ (スタブ) app/views/users/new.html.erb
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>
<p>This will be a signup page for new users.</p>

これで、少なくともサインインのルートを追加するまでの間、リンクと名前付きルートが完成しました (8)。結果を図 5.11の新規ユーザーのページ (URI /signup) に示します。

images/figures/new_signup_page_4th_edition
図 5.11: 新しいユーザー登録ページ (/signup)

演習

  1. もしまだ5.4.1.1の演習に取り掛かっていなければ、まずはリスト 5.41のように変更し、名前付きルートsignup_pathを使えるようにしてください。また、リスト 5.43で名前付きルートが使えるようになったので、現時点でテストが greenになっていることを確認してください。
  2. 先ほどのテストが正しく動いていることを確認するため、signupルールの部分をコメントアウトし、テスト redになることを確認してください。確認できたら、コメントアウトを解除して greenの状態に戻してください。
  3. リスト 5.32の統合テストにsignupページにアクセスするコードを追加してください (getメソッドを使います)。コードを追加したら実際にテストを実行し、結果が正しいことを確認してください。 ヒント: リスト 5.36で紹介したfull_titleヘルパーを使ってみてください。

5.5 最後に

この章では、アプリケーションのレイアウトを形にし、ルーティングを洗練させました。 本書では、以後サンプルアプリケーションを肉付けすることに専念します。最初に、ユーザー登録、サインイン、サインアウトできるユーザーを追加します。次に、マイクロポストを追加します。最後に、他のユーザーをフォローできるようにします。

Gitを使っている方は、この時点でmasterブランチに変更をマージしてください。

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

続いて、テストスイートを実行して greenになるか確認し、問題なければBitbucketにプッシュします。

$ rails test
$ git push

最後に、Herokuへデプロイします。

$ git push heroku

デプロイが無事に終わると、本番環境でサンプルアプリケーションが動いているはずです (図 5.12)。

images/figures/layout_production
図 5.12: 本番環境で動くサンプルアプリケーション

5.5.1 本章のまとめ

  • HTML5を使ってheaderやfooter、logoやbodyといったコンテンツのレイアウトを定義しました
  • Railsのパーシャルは効率化のために使われ、別ファイルにマークアップを切り出すことができます
  • CSSは、CSSクラスとidを使ってレイアウトやデザインを調整します
  • Bootstrapフレームワークを使うと、いい感じのデザインを素早く実装できる
  • SassとAsset Pipelineは、(開発効率のために切り分けられた) CSSの冗長な部分を圧縮し、本番環境に最適化した結果を出力する
  • Railsのルーティングでは自由にルールを定義することができ、また、その際に名前付きルートも使えるようになる
  • 統合テストは、ブラウザによるページ間の遷移を効率的にシミュレートする
  1. Colm Tuiteの多大な貢献により、サンプルアプリケーションをBootstrap CSSのフレームワークに変換することができました。感謝します。 
  2. Ruby on Railsチュートリアルのモックアップは、「Mockingbird」という素晴らしいモックアップ作成サービスで作られています。 
  3. shimshivという単語は、今回の用途ではどちらでも大丈夫です。shimの意味は「洗う機械、もしくは薄い物質を整理しフィットさせるためのモノ、あるいは服を削除すること」なので、意味合いとしては前者が正しいです。ちなみに後者は「ナイフ、もしくは武器として使う剃刀」という意味なので、おそらく原著者である Sjoerd Visscherのちょっとしたイタズラ心でしょう。 
  4. CSSクラスは、Rubyのクラスとはまったく関係がありません。 
  5. スペースを入れると見栄えが変わるかもしれませんが、3.4.1で触れたようにHTMLは重複する空白を無視するのでどちらでも大丈夫です。 
  6. このロゴ画像は実はちょっと古いロゴです。ただ最新のロゴは拡張可能なベクター画像 (SVG) になっていて、やや扱いには手間がかかります。今回はサッと済ませてしまいたいので古いロゴ画像を使っています。 
  7. 既にお気づきだと思いますが、imgタグは<img>...</img>と書いても良いのですが、一般的には<img ... />と書きます。このような書式のタグを閉じタグと呼びます。 
  8. 画像の引用元とライセンス: https://www.flickr.com/photos/deborah_s_perspective/14144861329 on 2016-01-09. Copyright © 2009 by Deborah (改変不可の Creative Commons Attribution 2.0 Generic ライセンス) 
  9. これまでと同様に、Gemfileで指定した各gemのバージョンはgemfiles-4th-ed.railstutorial.orgと一致している必要があります。もしうまく次に進めない場合はチェックしてみてください。 
  10. Asset PipelineではLessを使うこともできます。詳しくはless-rails-bootstrap gemを参照してください。 
  11. もしこのステップが摩訶不思議に思えたら、次のように考えてみましょう。「私はただbootstrap-sassのREADMEファイルに従っているのだ」と。 
  12. 多くのRails開発者は、異なるビューの間で共通に使用するパーシャルを保存するディレクトリとして、sharedディレクトリを使用します。 著者は、複数のビューで共有するユーティリティパーシャルについてはsharedフォルダに保存し、文字どおり全ページ (サイトレイアウトの一部として) 共通のパーシャルについてはlayoutsディレクトリへ保存することを好んでいます (sharedディレクトリは7で作成します)。 著者はこのように分割保存するのが論理的であると考えますが、sharedフォルダにすべて保存しても問題なく動作します。 
  13. footerタグと.footerクラスを両方使用していることについて疑問に思う方がいるかもしれません。 その理由は、footerタグとする方が読み手にとって意味が明確であるのと、.footerクラスはBootstrapで使用するためです。 footerdivに置き換えても動作は変わりません。 
  14. このチュートリアル構成は、Michael Erasmusによる素晴らしいブログ記事「5分でわかるRails 3のAsset Pipeline (英語)」をもとにしています。 詳細についてはRailsガイドの「アセットパイプライン」の項を参照してください。 
  15. Sassはもう1つの全く新しい文法もサポートしています。この文法は冗長性が少ない (括弧が少ない) 新しい言語と言えるのですが、ただ既存のプロジェクトには若干不便であり、既にCSSに慣れ親しんだ人にとっては学習が面倒でもあります。 
  16. 何人かの開発者は「1つのテストに複数のアサーションを入れるべきではない」と強く主張するでしょう。 この演習は不必要に複雑で、もし各テストの直前に共通のセットアップ用タスクがあれば、たしかに不要な負荷がかかることでしょう。 しかし、よく書かれたテストは一貫したストーリーのようになり、人間にとって理解しやすいです。ストーリーを独立した場面ごとに分割されてしまうと、物語調ではなくなってしまいます。このことから、複数のアサーションを1つのテストにまとめるようにして、(minitestを通して) Rubyにどのセリフで間違ったのかを話させるようにしています。 
Railsチュートリアルは,Ruby/Rails のアジャイル開発を得意とする YassLab によって運営・保守されております.
継続的に良いコンテンツを提供する為に,電子書籍解説動画のご購入を検討して頂けると幸いです m(_ _)m
スポンサーシップや商用利用などに関するご相談がありましたら,お問い合わせページよりお気軽にご連絡ください :)