# 5章 ## 構造を追加する rails tutorialではHTML5を使うが、旧式のIE(Internet Explorer)では使えない可能性があるため、javaScriptのコードを使い回避する。通称: HTML5 shim (or shiv) **app/views/layouts/application.html.erb** ```javascript <!--[if lt IE 9]> <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/r29/html5.min.js"> </script> <![endif]--> ``` IEのバージョンが9未満の場合、HTML5 shimを読み込む。 **link_to** :Railsヘルパーで第一引数にリンクテキスト、第二引数にURL、第三引数はあってもなくてもよい。 **app/views/layouts/application.html.erb** ```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> ``` これはブラウザに反映されると ```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> ``` のようになる。 **app/views/static_pages/home.html.erb** ```ruby <%= link_to image_tag("rails.png", alt: "Rails logo"), 'http://rubyonrails.org/' %> ``` これも ```ruby img alt="Rails logo" src="/assets/rails-9308b8f92fea4c19a3a0d8385b494526.png" /> ``` になる。ここでassets/imagesではなく、assets/画像で紐づけることでより高速になる。 ## 演習 1.Webページと言ったらネコ画像、というぐらいにはWebにはネコ画像が溢れていますよね。リスト 5.4のコマンドを使って、図 5.3のネコ画像をダウンロードしてきましょう。 A. **/sample_app** ```ruby curl -OL cdn.learnenough.com/kitten.jpg ```   2.mvコマンドを使って、ダウンロードしたkitten.jpgファイルを適切なアセットディレクトリに移動してください (参考: 5.2.1)。 A. **/sample_app** ```ruby mv kitten.jpg ./app/assets/images/ ```   3.image_tagを使って、kitten.jpg画像を表示してみてください (図 5.4)。 A. **app/views/static_peges/home.html.erb** ```ruby <%= image_tag("kitten.jpg", alt: "kitten logo") %> ``` を追加。   ## BoostrapとカスタムCSS もう一度確認。 **ヘルパー(helper)とは** ある動作を処理する場合にメソッドかして扱えるようにRailsに組み込まれた機能。開発を効率化するもの。 **link_to、form_with、label_for、image_tag、render** などがある。 **特にviewをシンプルにするためのもの**   **Bootstrapとは** Twitterが作成したフレームワーク。 ・javascript、html、cssなどの知識がなくても簡単に扱える。 ・モバイルファーストで、レスポンシブ(pc,mobile)のどちらの画面対応も簡単にできる。   Bootstrapフレームワークでは、 **LESS CSS(CSSの簡単なやつ)** を使っている。 Railsでは、(LESSと非常によく似た) Sass言語をサポートしている。 **なので、LESSをSass変換できればよい。**   そのためのbootstrap-sass gemがある。 ちなみに拡張子.scssは(Sassy CSS)でCSSを拡張した言語。Sassyはスラング?で「生意気な」「魅力的な」「元気な」などの意味。 Bootstrap CSSを導入するには、 **app/assets/stylesheets/custom.scss** ```css @import "bootstrap-sprockets"; @import "bootstrap"; ``` を追加する。一行目で読み込み、二行目で導入。また、ブラウザで反映させるには一度railsサーバーを再起動する必要がある。 navbar, nav, navbar-nav, navbar-right, container, jumbotron, btn, btn-lg, btn-primaryなどBootstrapにおいて特別な意味を持つのでBootstrapのCSSを追加したとき、これらのスタイルも自動に適用される。   次に、すべてのページに適応される共通のスタイルをCSSに追加する。 **app/assets/stylesheets/custom.scss** ```css @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; } ``` ### タグの対してのスタイル ```css body { padding-top: 60px; } ``` ### クラスに対してのスタイル ```css .center { text-align: center; } ``` ### idに対してのスタイル ```css # ~ { } ``` Bootstrapには洗練されたタイポグラフィーを利用できるCSSルールがある。 **タイポグラフィーとは** 活字(あるいは一定の文字の形状を複製し反復使用して印刷するための媒体)を用い、それを適切に配列することで、印刷物における文字の体裁を整える技芸である。from wiki まあ、文字サイズとか、色とかの統一?だととらえる。   **app/assets/stylesheets/custom.scss** ```css @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; } ```   headerも同様にきれいにする。 **app/assets/stylesheets/custom.scss** ```css @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; } ```   ## 演習 1.リスト 5.10を参考にして、5.1.1.1で使ったネコ画像をコメントアウトしてみてください。また、ブラウザのHTMLインスペクタ機能を使って、コメントアウトするとHTMLのソースからも消えていることを確認してみてください。 A. ```ruby <%#= image_tag("kitten.jpg", alt: "Kitten") %> ``` に変更。   2.リスト 5.11のコードをcustom.scssに追加し、すべての画像を非表示にしてみてください。うまくいけば、Railsのロゴ画像がHomeページから消えるはずです。先ほどと同様にインスペクタ機能を使って、今度はHTMLのソースコードは残ったままで、画像だけが表示されなくなっていることを確認してみてください。 A. ```css img { display: none; } ``` インスペクタにコードはあるが、画像は表示されない。 ![7pay](https://pbs.twimg.com/media/D-nDrNKVAAExpnP.jpg) これが有名な7payのやつ(笑)   ## パーシャル(partial) header、bodyの部分を分割し、使いまわしたり、見やすくするようなもの。   パーシャルを利用すると以下のようになる **app/views/layouts/application.html.erb** ```html <!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** ```ruby <%= render 'layouts/shim' %> ``` Railsヘルパー renderを使い、 **app/views/layouts/_shim.html.erb** というファイルを探し挿入。   ここで、 **_shim.html.erb** にアンダーバーが使われている。これは規約、ルールである。   **app/views/layouts/_shim.html.erb** ```html <!--[if lt IE 9]> <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/r29/html5.min.js"> </script> <![endif]--> ```   **app/views/layouts/_header.html.erb** ```html <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もやっておく。 **app/views/layouts/_footer.html.erb** ```html <footer class="footer"> <small> The <a href="https://railstutorial.jp/">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> ```   変更を加えたapplication.html.erb **app/views/layouts/application.html.erb** ```html <!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 %> <%= render 'layouts/footer' %> </div> </body> </html> ``` footerのCSSも整える。   ## 演習 1.Railsがデフォルトで生成するheadタグの部分を、リスト 5.18のようにrenderに置き換えてみてください。ヒント: 単純に削除してしまうと後でパーシャルを1から書き直す必要が出てくるので、削除する前にどこかに退避しておきましょう。 A. **app/views/layouts/application.html.erb** ```html <!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> ```   2.リスト 5.18のようなパーシャルはまだ作っていないので、現時点ではテストは redになっているはずです。実際にテストを実行して確認してみましょう。 A. 5 tests, 0 assertions, 0 failures, 5 errors, 0 skips   3.layoutsディレクトリにheadタグ用のパーシャルを作成し、先ほど退避しておいたコードを書き込み、最後にテストが green に戻ることを確認しましょう。 A. **app/views/layouts/_rails_default.html.erb** を作成し、コメントアウトしたものを張り付ける。 テストすると、 5 tests, 9 assertions, 0 failures, 0 errors, 0 skips グリーンになる。   ## Sassとパイプライン ### アセットパイプライン https://qiita.com/hogehoge1234/items/9a94ebc93c5f937502cd 要するに、rails開発者の視点からは3つの機能を理解する必要があり、それらが、 アセットディレクトリ、マニフェストファイル、プリプロセッサエンジンである。 ・アセットディレクトリは、CSS用、画像用、javascript用と、ディレクトリが分かれており、開発しやすくなっているということ。 ・マニュフェストファイルとは、css、jsそれぞれのファイルの代表みたいなもので、いくつかのcss、jsをまとめたもの。実際にアセットをまとめる処理を行うのはSprocketsというgem。アプリケーションのCSS用マニフェストファイルは、**app/assets/stylesheets/application.css** ・プリプロセッサエンジンとは、様々な拡張子を統合し、ブラウザに表示されるようなビューを作る。その際に、無駄な空白などを削減し、処理スピードを早くするようなデータ整形を行うもの。   **開発側に開発する際の分かりやすさ、見やすさ、開発しやすさを与え、ユーザ側に処理スピードの速さを与える。**   ### Sass CSS本体を抽象化したフォーマット。 重要な機能として、 **ネスト** と **変数** がある。 ### ネスト **app/assets/stylesheets/custom.scss** ```css /* 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 small { float: left; } footer ul { float: right; list-style: none; } footer ul li { float: left; margin-left: 15px; } ``` これを ```css 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; } } } ``` このように書けること。   ### 変数 色などの分かりづらい値は変数でまとめた方が分かりやすい。本来$マークを使い以下のようにまとめる。 ```css $light-gray: #777; . . . h2 { . . . color: $light-gray; } . . . footer { . . . color: $light-gray; } ``` しかし、Bootstrapフレームワークでは、多くの色に対して変数名を定義しているので、いちいち変数を定義しなくても用意されているものが多い。 実際に変換したものが以下のようになる。 **app/assets/stylesheets/custom.scss** ```css @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; } } } ```   ## 演習 1.5.2.2で提案したように、footerのCSSを手作業で変換してみましょう。具体的には、リスト 5.17の内容を1つずつ変換していき、リスト 5.20のようにしてみてください。 A. 省略。   ## 名前付きルート railsでは名前付きルートを使うことが柔軟性があり、慣例となっている。 ルートURLを定義することで、root_pathやroot_urlといったメソッドを通してURLを参照することができる。 具体的には **config/routes.rb** ```ruby get 'static_pages/help' ``` を ```ruby get '/help', to: 'static_pages#help' ``` にする。これにより名前付きルートも扱うことができる。 ```rails help_path -> '/help' help_url -> 'http://www.example.com/help' ``` **config/route.rb** ```ruby Rails.application.routes.draw do root 'static_pages#home' get 'static_pages/home' get 'static_pages/help' get 'static_pages/about' get 'static_pages/contact' end ``` を ```ruby 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 ``` このように変更する。   ## 演習 1.実は名前付きルートは、as:オプションを使って変更することができます。有名なFar Sideの漫画に倣って、Helpページの名前付きルートをhelfに変更してみてください (リスト 5.29)。 A. コピペ   2.先ほどの変更により、テストが redになっていることを確認してください。リスト 5.28を参考にルーティングを更新して、テストを greenにして見てください。 A. テスト 5 tests, 7 assertions, 0 failures, 1 errors, 0 skips **static_peges_controller_test,rb** ```ruby test "should get help" do get helf_path assert_response :success assert_select "title", "Help | #{@base_title}" end ``` テスト。5 tests, 9 assertions, 0 failures, 0 errors, 0 skips   3.エディタのUndo機能を使って、今回の演習で行った変更を元に戻して見てください。 A. 省略。   ## 名前付きルート **app/views/layouts/_header.html.erb** のlink_toメソッドの第二引数に名前付きルートを置く。 ```html <%= link_to "About", '#' %> ``` を ```ruby <%= link_to "About", about_path %> ``` のようにしておく。 headerやfooterのパーシャルを変更。   ## 演習 1.リスト 5.29のようにhelfルーティングを作成し、レイアウトのリンクを更新してみてください。 A. route.rb、_header.html.erb、_footer.html.erb、static_pages_cotroller_test.rbのパスを"helf_path"にする。   2.前回の演習と同様に、エディタのUndo機能を使ってこの演習で行った変更を元に戻してみてください。 A. 省略。   ## 統合テスト 「統合テスト (Integration Test)」を使って一連の作業を自動化。統合テストを使うと、アプリケーションの動作を端から端まで (end-to-end) シミュレートしてテストすることができる。コントローラのテストと違い、リンクが正しく動いているかどうかチェックするテスト。 ```rails rails generate integration_test site_layout ``` でテストを作る。 テストの中身は **test/integration/site_layout_test.rb** ```ruby 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 ```   ```ruby get root_path ``` この行では、ルートURL (Homeページ) にGETリクエストを送る。   ```ruby assert_template 'static_pages/home' ``` この行では、assert_templateメソッドを使って、Homeページが正しいビューを描画しているかどうか確かめている。   以下の行では、assert_selectを使って、homeページにaタグとhref属性をオプションで指定して調べている感じ。   "?"には次の引数、名前付きルートが入る。   assert_selectは多くのオプションがあるが、あまり複雑なテストをしないのが賢明。 統合テストのみ行いたいときは ```ruby rails test:integration ``` を実行する。 それが終わったら全体を通して ```ruby rails test ```   ## 演習 1.footerパーシャルのabout_pathをcontact_pathに変更してみて、テストが正しくエラーを捕まえてくれるかどうか確認してみてください。 A. **footer.html.erb** を変更し、テスト(rails test:integration) 1 tests, 4 assertions, 1 failures, 0 errors, 0 skips   2.リスト 5.35で示すように、Applicationヘルパーで使っているfull_titleヘルパーを、test環境でも使えるようにすると便利です。こうしておくと、リスト 5.36のようなコードを使って、正しいタイトルをテストすることができます。ただし、これは完璧なテストではありません。例えばベースタイトルに「Ruby on Rails Tutoial」といった誤字があったとしても、このテストでは発見することができないでしょう。この問題を解決するためには、full_titleヘルパーに対するテストを書く必要があります。そこで、Applicationヘルパーをテストするファイルを作成し、リスト 5.37のFILL_INの部分を適切なコードに置き換えてみてください。ヒント: リスト 5.37ではassert_equal <期待される値>, <実際の値>といった形で使っていましたが、内部では==演算子で期待される値と実際の値を比較し、正しいかどうかのテストをしています。 A. **test/test_helper.rb** ```ruby include ApplicationHelper ``` を追加。   **test/integration/site_layout_test.rb** ```ruby get contact_path assert_select "title", full_title("Contact") ``` を追加。   **test/helpers/application_helper_test.rb** ```ruby 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 ``` とする。    ## Userコントローラ Userコントローラを作成(newアクションを追加) ```ruby rails generate controller Users new ``` この時点で、コントローラ、ビュー、ルート、ヘルパー、テストなどが自動生成される。   ## 演習 1.表 5.1を参考にしながらリスト 5.41を変更し、users_new_urlではなくsignup_pathを使えるようにしてみてください。 A. **config/routes.rb** ```ruby get '/signup', to: 'users#new' ```   **test/controller/usets_controller_test.rb** ```ruby require 'test_helper' class UsersControllerTest < ActionDispatch::IntegrationTest test "should get new" do get signup_path assert_response :success end end ```   2.先ほどの変更を加えたことにより、テストが redになったことを確認してください。なお、この演習はテスト駆動開発 (コラム 3.3) で説明した red/green のリズムを作ることを目的としています。このテストは次の5.4.2で greenになるよう修正します。 **test/controllers/users_controller_test.rb** ```ruby require 'test_helper' class UsersControllerTest < ActionDispatch::IntegrationTest test "should get new" do get users_new_url assert_response :success end end ``` users_new_urlがsignup_pathでないのでREDになる。   ## ユーザ登録用URL **config/routes.rb** ```ruby get '/signup', to: 'users#new' ``` で名前付きルートの定義。   **test/controllers/users_controller_test.rb** ```ruby require 'test_helper' class UsersControllerTest < ActionDispatch::IntegrationTest test "should get new" do get signup_path assert_response :success end end ``` テストのルートも変更。   **app/views/static_pages/home.html.erb** ```ruby <%= link_to "Sign up now!", signup_path, class: "btn btn-lg btn-primary" %> ``` 名前付きルートを追加。   ## 演習 1.もしまだ5.4.1.1の演習に取り掛かっていなければ、まずはリスト 5.41のように変更し、名前付きルートsignup_pathを使えるようにしてください。また、リスト 5.43で名前付きルートが使えるようになったので、現時点でテストが greenになっていることを確認してください。 A. rails tをし、GREEN   2.先ほどのテストが正しく動いていることを確認するため、signupルートの部分をコメントアウトし、テスト redになることを確認してください。確認できたら、コメントアウトを解除して greenの状態に戻してください。 A. コメントアウトし、rails tでRED   3.リスト 5.32の統合テストにsignupページにアクセスするコードを追加してください (getメソッドを使います)。コードを追加したら実際にテストを実行し、結果が正しいことを確認してください。ヒント: リスト 5.36で紹介したfull_titleヘルパーを使ってみてください。 A. **test/integration/site_layout_test.rb** にて ```ruby 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 get contact_path assert_select "title", full_title("Contact") get signup_path assert_select "title", full_title("Sign up") end end ``` のように、sign_pathについての統合テストを追加。 ## 最後に いつも通りgitとheorkuにpush     ## 分からなかったこと 統合テストが出てきて今までのテストと何が違うのかわからなくなった。 <u>[テストについて1](https://qiita.com/duka/items/2d724ea2226984cb544f)</u> ↑を見ると少し理解できると思う。 まとめると、 テストは3つあり、単体テスト、機能テスト、統合テストに分けられ 3章や、今までやってきたテストは、単体テスト 5章、今回出てきた ***rails test:integration*** は統合テスト だと思う。 機能テストはよくわからないが、下の方が分かりやすいことが書いてあった。 <u>[テストについて2](https://www.ryotaku.com/entry/2019/05/02/%E3%83%86%E3%82%B9%E3%83%88%E3%82%B3%E3%83%BC%E3%83%89%E3%80%81%E5%8D%98%E4%BD%93%E3%83%86%E3%82%B9%E3%83%88%E3%81%8B%E3%82%89%E6%9B%B8%E3%81%8F%E3%81%8B%EF%BC%9F%E7%B5%B1%E5%90%88%E3%83%86)</u> 要するに ***単体テストとは、コントローラーのメソッド単位など 一機能毎に正常動作するかチェックできるテスト。*** ***統合テストとは、編集ボタンを押してフォームに入力し送信ボタンを押すといった 実際にユーザーが行う一連の操作が正常に実行できるかチェックするテスト。***