railsチュートリアルまとめ5 レイアウトを作成する

# 個人的リマインド用
参考
[Ruby on Rails チュートリアル プロダクト開発の０→１を学ぼう](https://railstutorial.jp/)

## レイアウトを作成する
```erb
app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title><%= full_title(yield(:title)) %></title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta charset="utf-8">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
  </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>
```
**link_to**
Railsでは、リンクを生成するために、Railsヘルパーのlink_toを使う。第一引数にリンクテキスト、第2引数にURLを書くが、このURLに関しては名前付きルーティングを使用する。(後々説明)

**画像挿入**
```
<%= link_to image_tag("rails.svg", alt: "Rails logo", width: "200"),
                      "https://rubyonrails.org/" %>
```
link_toでは、引数として画像ファイルのパスと任意のオプションハッシュを受け取るimage_tagヘルパーの機能が記されている。画像を表示するためには、rails.svg(今回の場合)というロゴ画像ファイルを加える必要がある。**app/assets/images**の下に置く。

HTMLで画像を見てみると
```
<img alt="Rails logo" width="200px" src="/assets/rails-<long string>.svg">
```
long stringの部分は、ファイル名が一意になるようにRailsによって追加される。例えば、画像ファイルを新しい画像に更新した時に、ブラウザ内に保存されたキャッシュに意図的にヒットさせないようにするための仕組み。
### BootstrapとカスタムCSS
**Bootstrapの追加**
bootstrap-sassというgemを使って導入する。BootstrapではLESS CSS言語を使っているが、RailsのアセットパイプラインではデフォルトでSass言語をサポートしている。bootstrap-sassはLESSをSassに変換し、利用できるようにするもの。ちなみにRails7からは、アセットパイプラインのSass機能がsassc-railsという別のgemに切り出された。
```
Gemfile

gem "rails"...
gem "bootstrap-sass", "3.4.1"
gem "sassc-rails",    "2.1.2"
.
.
```
これでbundle

rails generateコマンドを実行することでコントローラごとに分けられたCSSファイルが自動的に生成されるが、チュートリアルではすべてのCSSを1つにまとめる方針をとっている。
```
touch app/assets/stylesheets/custom.scss
```
app/assets/stylesheets/はアセットパイプラインの一部であり、このディレクトリに置かれたスタイルシートはapplication.cssの一部としてWebサイトのレイアウトに読み込まれる。

カスタムCSS用のファイルを作成したら、@importを使って、Bootstrapとそれに関連するSprocketsを読み込む。
```
app/assets/stylesheets/custom.scss

@import "bootstrap-sprockets";
@import "bootstrap";
```
### パーシャル
Railsでは**パーシャル(partial)を**使うことで、共通したコードを1箇所にまとめられる。
```erb
app/views/layouts/application.html.erb

<!DOCTYPE html>
<html>
  <head>
    <title><%= full_title(yield(:title)) %></title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta charset="utf-8">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
  </head>
  <body>
    <%= render 'layouts/header' %>　←ここ
    <div class="container">
      <%= yield %>
      <%= render 'layouts/footer' %> ←ここ
    </div>
  </body>
</html>
```
```
<%= render 'layouts/header' %>
```
この行ではapp/views/layouts/_header.html.erbというファイルを探してその内容を評価し、結果をビューに挿入している。
_header~について、_はパーシャルで使う普遍的な命名規則であり、一目見ただけでパーシャルとわかる。
上のコードを動かすにはパーシャルファイルをつくらないといけない。
```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>
```
ついでにfooterのパーシャルファイルも作る
```erb
app/views/layouts/_footer.html.erb

<footer class="footer">
  <small>
    The <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
    by <a href="https://www.michaelhartl.com/">Michael Hartl</a>
  </small>
  <nav>
    <ul>
      <li><%= link_to "About",   '#' %></li>
      <li><%= link_to "Contact", '#' %></li>
      <li><a href="https://news.railstutorial.org/">News</a></li>
    </ul>
  </nav>
</footer>
```
### Sassとアセットパイプライン
**アセットパイプライン**とは、CSSや画像などの静的コンテンツの作成と管理を大幅に強化するもの。
以下3つの主要機能の理解が必要。
また**アセット**とは、Webアプリケーションの直接のレスポンス以外の構成要素のこと。JS、CSS、画像などがこれに当たる。

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

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

custom.scssは今回のアプリ固有のアセットなので、app/assetsに置くのが正解
```
ls app/assets/
config images stylesheet
```

**マニフェストファイル**
静的ファイルを上記の場所へそれぞれ配置すれば、マニフェストファイルを使って、それらをどうのように1つにまとめるか、Railsに指示することができる。実際にアセットをまとめる処理を行うのはSprocketsというgem。また、マニフェストファイルはCSSやJSには適用されるが、画像ファイルには適用されない。

**プリプロセッサエンジン**
Railsは、必要なアセットをディレクトリに配置してまとめた後、さまざまなプリプロセッサエンジンを実行して結合することで、ブラウザに配信できるようにする。

**アセットパイプラインの最大のメリットの1つは**、本番アプリで効率的になるよう最適化されたアセットを自動的に生成できること。開発環境ではプログラマが書きやすいようにして、本番環境では効率的になるようまとめる。アセットパイプラインが全てのスタイルシートを結合して、application.cssにまとめる。

### Sass
Sassに関しては別途学習

### 名前付きルーティング
Railsではリンク付のさい名前付きルーティングで設定するのが慣習
```
<a href="/static_pages/about">About</a>
```
ではなく
```
<%= link_to "About", about_path %>
```
上のようにすることでコードの意味が分かりやすくなり、about_pathの定義を変えれば、about_pathが使われているすべてのURLを変更できるため。

今回のアプリのroutesマッピング
|ページ名|URL|名前付きルーティング|
|---|---|---|
|Home|/|root_path|
|About|/about|about_path|
|Help|/help|help_path|
|Contact|/contact|contact_path|
|Sign up|/signup|signup_path|
|Log in|/login|login_path|
### RailsのルートURL
ルートURLを定義すると、root_pathやroot_urlといったメソッドを通して、URLを参照することができる。
```
root_path -> '/'
root_url -> 'https://www.example.com/'
```
基本的には_pathを使い、リダイレクトの時のみ_urlを使う。

**名前付きルーティングの定義**
```
get "static_pages/help"
から
get  "/help", to: "static_pages#help"
に変更
```
GETリクエストが/helpに送信された時、StaticPagesコントローラのhelpアクションを呼び出してくれる。また、hekp_pathやhelp_urlなどの名前付きルーティングも使えるようになる。
### リンクのテスト
リンクを埋め込んだからテストをしたい。しかし、それぞれのリンクを踏んで確かめていくのは骨が折れるので、**統合テスト**を使って一連の作業を自動化する。統合テストを使うと、アプリケーションの動作を端から端までシミュレートしテストできる。まずはテストのテンプレートを作成。
```
rails g integration_test site_layout (できるファイル名はsite_layout_test)
```
今回の目的はアプリケーションのHTML構造を調べ、レイアウトの各リンクが正しく動作するかテストする。
1. ルートURL(Homeページ)にGETリクエストを送る。
2. 正しいページテンプレートが描画されているかどうか確かめる。
3. Home,Help,About,Contactの各ページへのリンクが正しく動くか確かめる

**assert_templete**メソッドを使って、Homeページが正しいビューをレンダリングしているか確かめる。
```ruby
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
```
```
assert_select "a[href=?]", about_path
```
について。
上の行では?をabout_pathに置換している。つまり
```
<a href="/about">...</a>
```
こんなHTMLがあるかをチェックしている。

```
assert_select "a[href=?]", root_path, count: 2
```
について。
今回はルートURLへのリンクが2つある。こういう書き方をすることで個数を調べられる。

**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>|
### ユーザー登録の最初のステップ
最初にUsersコントローラを作る。新規ユーザーを作るアクションをnewとする。
```
rails g controller Users new
```
ビューとテストも一緒に作成される。

最後にルートの設定
```
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
```
signup_pathが使えるようになった。