ハイパーニートプログラマーへの道

頑張ったり頑張らなかったり

Rails Tutorial Chapter5をやる 断片的、そして適当なメモ

f:id:noriyo_tcp:20150222211120p:plainRails Tutorialも第5章です。メモを取りながらやっているのですが、いかんせん日にちが経っている(実は今10章まで進んだw)
なのでほとんどメモをコピペしてるだけですが・・・。

第4章はRailsというよりRubyの基本的な構文についてなので、初心者の方はやるとよろしいかと存じますが、まあサラッとチェックしただけに留めて次へ行きます。

この章で学ぶ(学んだ)こと(適当訳)

Chapter 5: Filling in the layout | Ruby on Rails Tutorial (3rd Ed.) | Softcover.io

  • HTML5を使う。ロゴ、ヘッダー、フッター、メインのコンテントなどサイトのレイアウトを決めていく。
  • パーシャルを使ってマークアップ複数のファイルに切り分けていく。便利。
  • CSSのクラスやらidやらを使っていきます。
  • Bootstrapも使う。手っ取り早くいい感じのデザインができます。
  • SassとアセットパイプラインCSSの重複を排除し、その結果を本番環境用に効率的にパッケージングすることができる。
  • Railsはカスタムのルーティングの決まりがあって、それにより名前付きのルートを提供できる。
  • 結合テストにより、ブラウザでクリックしてページ遷移、というのを効果的にシュミレートすることができる。

いったいどうゆうことなんでしょうね(半ギレ)


Bootstrapの導入

とうとうBootstrapを導入して、本格的にレイアウト作っていく、ということで。

まず、今までホーム、ヘルプ、ログインページを作ったはいいんですけど、個々へアクセスするためのリンクがないなと。

マスターからブランチを切ります。

$ git checkout -b filling-in-layout

レイアウトのカスタマイズ

各画面に共通するレイアウトを作っていきます。

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

HTML5に対応してないless than IE9に対してはhtml5shivを使うようにするぜと。
コメントアウトしているのが奇妙だが、これでいいの・・・かな?

日本のブラウザバージョン別シェアグラフ2014 (StatCounter Global Statsより)

ここを見るとIE9以前もちらほらありますな。

ヘッダー

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

navbarなどのクラスは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>
  </ul>
</nav>

link_toヘルパーを使っていくよと。ただしリンク先は仮で。

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

要はこういう意味合いになる。HTML5だと。

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

この部分に各画面の個別のレイアウトが表示されていきます。

ホーム画面のカスタマイズ

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://www.railstutorial.org/">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/' %>

jumbotronは今まで使ったことなかったかも。でかい。
btn-lgもBootstrapのクラス。大きめのボタンになる。

http://getbootstrap.com/components/#jumbotron

画面下部にlink_to,image_tag 画像にリンクを張っているんですね。

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

image_tag使用しているのはいいけど、肝心の画像がないですよと。
Rails Tutorialのロゴを取ってくることができるようです。
アプリのルートディレクトリ上にて

$ curl -O http://rubyonrails.org/images/rails.png                                       
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current                                                                                    
                                 Dload  Upload   Total   Spent    Left  Speed                                                                                      
100 13036  100 13036    0     0  22979      0 --:--:-- --:--:-- --:--:-- 38228                                                                                     
$ ls                                                                                    
app  bin  config  config.ru  db  Gemfile  Gemfile.lock  Guardfile  layout_file  lib  log  public  rails.png  Rakefile  README.md  test  tmp  vendor

こうしてルートにDLしてからの、app/assets/images/に移動させる。

$ mv rails.png app/assets/images/

まだBootstrap導入してないのでこんな感じ。

f:id:noriyo_tcp:20150222210129p:plain


5.1.2 Bootstrap and custom CSS

Gemfileの編集

Bootstrapを導入します。RailsのアセットパイプラインでサポートしているSassも使えるように、bootstrap-sassを導入します。

source 'https://rubygems.org'

gem 'rails',                '4.2.0'
gem 'bootstrap-sass',       '3.2.0.0'
.
.
.
$ bundle install

カスタムCSSの作成

app/assets/stylesheetsにcustom.css.scssというファイルを作成します。

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

そしてそこでBootstrapのインポート。

@import "bootstrap-sprockets";
@import "bootstrap";

rails sすると、Bootstrapが適用されてる!

f:id:noriyo_tcp:20150222210512p:plain

さらにカスタマイズしていきます。

@import "bootstrap-sprockets";
@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;
}

全体のセッティング。.centerクラスの内容は文字を真ん中寄せにする。ちゃんとクラスの名前と内容を一致させているんだなあと。
これからCSSを書くときも気をつけていきたい点ですね。

f:id:noriyo_tcp:20150222210640p:plain

Typography

  • letter-spacing

letter-spacing−スタイルシートリファレンス

normal 標準の間隔にします。これが初期値です。 数値で指定 数値にpxやemやexなどの単位をつけて指定します。尚、pxとは1ピクセルを1とする単位で、実際に表示されるサイズは72dpiや96dpiといったモニタの解像度により変化します。また、emとはフォントの高さを1とする単位で、exとは小文字の「x」の高さを1とする単位です。

この場合-2pxとすることにより、文字の感覚がぎゅっと詰まった。

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

ここら辺はよくわからないなあ。先に.centertext-align: conter;と、h1margin-bottom: 10pxを指定しているので、ここでわざわざ指定し直す必要もないと思うんだけど。実際見た目も変わりない?なあ。

でもなんか様になってきたぞ〜。

ヘッダー部分のカスタマイズ

/* 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;
}

font-size: 1.7emなので、h2より大きいですね。
text-transform: uppercase;なんてのがあるんだ! タイトルが大文字になった!

んー、カコイイねー。

f:id:noriyo_tcp:20150222211120p:plain

5.1.3 Partials

共通レイアウトに記述していたこの部分を

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

パーシャルにして切り分けてしまおうと。

app/views/layouts/_shim.html.erbを作って、そこにIE9以前に対応する部分を突っ込む。

<!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' %>でそのパーシャルを表示させる。_はつけなくてよし。

の部分も_header.html.erbというパーシャルを作ってそこに突っ込む。

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>

フッターも作ります。
app/views/layouts/_footer.html.erb

<footer class="footer">
  <small>
    The <a href="http://www.railstutorial.org/">Ruby on Rails Tutorial</a>
    by <a href="http://www.michaelhartl.com/">Michael Hartl</a>
  </small>
  <nav>
    <ul>
      <li><%= link_to "About",   '#' %></li>
      <li><%= link_to "Contact", '#' %></li>
      <li><a href="http://news.railstutorial.org/">News</a></li>
    </ul>
  </nav>
</footer>

それらを共通レイアウトの中で表示

app/views/layouts/application.html.erb

<body>
    <%= render 'layouts/header' %>
    <div class="container">
      <%= yield %>
      <%= render 'layout/footer' %>
    </div>
  </body>

5.2.1 The asset pipeline

Nesting on Sass

.center {
  text-align: center;
}

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

Sassだとこのようにnestできる

.center {
  text-align: center;
  h1 {
    margin-bottom: 10px;
  }
}
#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に付加する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;
  }
}

#logo:hover => &:hoverになると。

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

footerのスタイルもこのようにネストできるが・・・なんかわけかわらんくなっとるw

Variables

Lessだと@gray-light: #777;というふうにするみたいだが、Sassだと$gray-light: #777;

BootstrapはLessだが、今の場合gem bootstrap-sassをインストールしてるので、Sassでよい。

http://getbootstrap.com/customize/#less-variables

5.3 Layout links

get 'static_pages/help'
get 'static_pages/about'
get 'static_pages/contact'

このままだと/static_pages/なんたらというurlになっちゃうので。

config/routes.db

  get 'help' => 'static_pages#help'
  get 'about' => 'static_pages#about'
  get 'contact' => 'static_pages#contact'

help_path -> '/help'
help_url -> 'http://www.example.com/help'

5.3.4 Layout link tests

Home画面のリンクが正しく表示されるかどうかを、いちいちポチポチ押して確認するのめんどいよねと。

Integration test

$ rails generate integration_test site_layout

複数のアクションやコントローラにまたがる挙動を検証するためのテスト

テスト(test) - Railsドキュメント

Note that the Rails generator automatically appends _test to the name of the test file.

https://www.railstutorial.org/book/filling_in_the_layout

ストファイルは_testが追記された形で生成される。

$ rails g integration_test site_layout                                                   
      invoke  test_unit                                                                                                                                            
      create    test/integration/site_layout_test.rb
require 'test_helper'

class SiteLayoutTest < ActionDispatch::IntegrationTest
  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
  • ルートにアクセス
  • static_pages/homeというテンプレートが表示されているか。
  • assert_selectセレクタを確認。
    • ルートへのリンクが2つあるか。
    • ヘルプ、アバウト、コンタクトへのそれぞれのリンクがあるか。

5.4 User signup: A first step

$ rails g controller Users new

config/routes.rb

get 'signup' => 'users#new'

integration testにおいて、signup_pathにアクセスした時に、ページタイトルが'Sign up'になってるかどうかテストしたい。

まず、page titleを設定しているのはApplicationHelperに定義したfull_titleヘルパーでした。その戻り値が正しいかどうかを確認すればいいわけです。

だからまず、test_helper.rbApplicationHelperをインクルードしないといけません。

test/test_helper.rb

 ENV['RAILS_ENV'] ||= 'test'
.
.
.
class ActiveSupport::TestCase
  fixtures :all
  include ApplicationHelper
  .
  .
  .
end

integration testでfull_titleヘルパーを使います。

require 'test_helper'

class SiteLayoutTest < ActionDispatch::IntegrationTest

  test "layout links" do
    get root_path
    .
    .
    .
    # ここから
    get signup_path # signup pageにアクセスしたときに・・・
    assert_select "title", full_title("Sign up") # <title>タグ内のテキストが"Sign up"になってるかどうか
  end
end

あれ? メモがここで終わってるなあ。このあとはサインアップ用のリンクを設定するなどの話なんですけど・・・だから早くブログに書けとあれほど(ry


5.4.2 Signup URL

https://www.railstutorial.org/book/filling_in_the_layout#sec-signup_url

config/routes.rb

Rails.application.routes.draw do
  root             'static_pages#home'
  get 'help'    => 'static_pages#help'
  get 'about'   => 'static_pages#about'
  get 'contact' => 'static_pages#contact'
  get 'signup'  => 'users#new' # ここ
end

users#newアクションに紐付いたsignupというルートを設定。

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://www.railstutorial.org/">Ruby on Rails Tutorial</a>
    sample application.
  </h2>

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

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

今までリンクに仮の#を設定していた部分にsignup_pathを設定。

対応するビューである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>

ページのタイトルはprovideを使用する。

f:id:noriyo_tcp:20150222213716p:plain

こんな感じで仮のnewページ。

f:id:noriyo_tcp:20150222213751p:plain

ページタイトルもSign up + ベースタイトルとなっている。


今章はまだRailsというよりはCSS(Sass)とかBootstrapとかの話かと。
軽くレイアウトと決めつつ進めていく感じ。しかしながらテストもでてきましたので、そこら辺もっと勉強していきたいなと。


その他

line-height−スタイルシートリファレンス

  • line-height

normal ブラウザが判断して行の高さを決定します。これが初期値です。

数値に単位をつけて指定

数値にpxやemやexなどの単位をつけて指定します。pxとは1ピクセルを1とする単位で、実際に表示されるサイズは72dpiや96dpiといったモニタの解像度により変化します。また、emとはフォントの高さを1とする単位で、exとは小文字の「x」の高さを1とする単位です。

数値のみで指定

単位をつけずに数値のみを指定すると、その数値にフォントのサイズを掛けた値が行の高さとなります。例えば「1.5」と指定すると「150%」や「1.5em」と指定した場合と同じになります。

%で指定

%値で指定します

恥ずかしながらまだまだCSSがよくわかってないなあ。

  • font-size

http://www.htmq.com/style/font-size.shtml

数値で指定

数値にpxやemやexなどの単位をつけて指定します。pxとは1ピクセルを1とする単位で、実際に表示されるサイズは72dpiや96dpiといったモニタの解像度により変化します。また、emとはフォントの高さを1とする単位で、exとは小文字の「x」の高さを1とする単位です。数値には負の値は指定できません。

%で指定

%値で指定します。

キーワードで指定

xx-small、x-small、small、medium、large、x-large、xx-largeの7段階があり、mediumが標準サイズです。1段階上がると1.2倍のサイズになります。また、smaller、largerを指定すると大きさが1段階上下します。


アセットを入れるところが何個かあるんだな。

In the latest version of Rails, there are three canonical directories for static assets, each with its own purpose:

app/assets: assets specific to the present application lib/assets: assets for libraries written by your dev team vendor/assets: assets from third-party vendors

(日本語版)
http://railstutorial.jp/chapters/filling-in-the-layout?version=4.0#sec-the_asset_pipeline

Rails 3.1以降では、静的ファイルを目的別に分類する、標準的な3つのディレクトリが使用されるようになりました。Rails 4.0でも同様です。

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