0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Railsチュートリアル第5章学習まとめ

Posted at

5.1.2BootstrapとカスタムCSS

個人的な学習メモまとめなので覚えてないところや重要だと思ったところをまとめていきます。

HTML要素に多くのCSSクラスを関連付けることで、CSSベースのレイアウト設計に柔軟性をもたらす。これらのクラスは主にBootstrap、Twitterが開発したCSSフレームワークに由来。
Bootstrapは、HTML5アプリケーションに容易に優れたWebデザインとユーザーインターフェイスを提供。
サンプルアプリケーションには、カスタムCSSルールとBootstrapを組み合わせて使用し、レスポンシブデザインを実現した。これにより、どの端末からでもアプリケーションが適切に表示され、見栄えが良くなる。

実際のclassにそれぞれBootstrap側で何に用いるのか定義付がしてあり
それらのClassを活用することで容易に優れたWEBデザインができるということみたいです。

この辺は実践で改めて勉強って感じですね。

5.1.3パーシャル(partial)

個人的にRails学習していく中で一番感動した機能です。

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" %>
    <%= javascript_importmap_tags %>
  </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>

このコードだととても長いですがRailsのパーシャル機能を使って以下にコードを短縮できます。
<body></body>の部分を<%= render 'layouts/header' %>に置き換えるだけ!
これだけでコードを簡略化できる優れものです。

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" %>
    <%= javascript_importmap_tags %>
  </head>
  <body>
    <%= render 'layouts/header' %>
    <div class="container">
      <%= yield %>
    </div>
  </body>
</html>

チュートリアルの説明要約だと下記です。
このテキストは、ERBテンプレート内でRubyの式を評価するために<%= ... %>記法を使って、_header.html.erbというパーシャルファイルの内容を評価し、ビューに挿入していることを説明しています。ファイル名の先頭にあるアンダースコアは、パーシャルファイルに一般的に用いられる命名規約であり、これによりディレクトリ中のパーシャルが一目で識別できることを示しています。

つまり<%= render 'layouts/header' %>
_header.html.erbに省略したコードが格納記述されているという解釈をしています。

そして実際にapp/views/layouts/_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>

このような形でパーシャルを用いる事でコード重複を避けコードのページ簡略化ができます。

5.2.1 アセットパイプライン

Rails開発者の視点からは、アセットディレクトリ、マニフェストファイル、プリプロセッサエンジンという、3つの主要な機能が理解の対象となりますとのこと。

よくわからないので咀嚼していきます。

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

app/assets: 現在のアプリケーション固有のアセット
lib/assets: あなたの開発チームによって作成されたライブラリ用のアセット
vendor/assets: サードパーティのアセット(デフォルトでは存在しません)

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

よってcustom.sccsはapp/assets/stylesheetsに配置するのが適切

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

この中で重要なコードは下記

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

以下引用
*= require_tree .はapp/assets/stylesheetsディレクトリ(サブディレクトリを含む)中のすべてのCSSファイルをアプリケーションCSSに含めるよう指示している。

*= require_selfはCSSの読み込みシーケンスの中で、application.css自身もその対象に含めるよう指示している。

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

用は説明書とCSSの含む範囲を指示しており、自身も含んでくれといってるわけですね。

・プリプロセッサエンジン
Railsは、必要なアセットをディレクトリに配置してまとめた後、様々なプリプロセッサエンジンを実行して結合することで、ブラウザに配信できるようにします。Railsでは、どのファイルに対してどのプリプロセッサを使うのかをファイル名の拡張子で判断します。ほとんどの場合、ファイル名の末尾にある拡張子が.erbであればERB用のプリプロセス(前処理)を実行し、.scssであればSass用のプリプロセスを実行します。

Railsは拡張子で判断して様々なファイルを結合しブラウザに配信することができるってことですね。

ここで1つ疑問がありまし/た。

これだけ分割していくと読み込みが遅くなって不便じゃないか?と
その答えはチュートリアルの下記にあったので要約しました。

アセットパイプラインは、開発と本番環境の両方に最適化されたアセット管理を提供します。開発では、ファイルが読みやすい形式で分割されることが一般的ですが、この方法は本番環境での効率を低下させます。アセットパイプラインを利用すると、開発中は読みやすさを保ちつつ、本番環境ではCSSやJavaScriptを1つのファイルに結合し、不要な空白やインデントを削除してファイルサイズを最小化することで、ページの読み込み速度を向上させます。また、本番環境でのアセットコンパイルの方法はプラットフォームに依存しますが、例えばRenderではデフォルトで設定されたコマンドを利用することができます。

アセットパイプラインを利用すれば開発中のコードは読みやすいしエラーもどこにあるかわかりやすい
本番環境はRailsは1つのファイルに結合する性質があり不要なものは削除するので
読み込みも早い。こう解釈しています。

つまりRailsは従来のHTML/CSS/JavaScriptの読み込みのことも考えて作られてるってことですね。
すげー。

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

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

何やらcssがパワーアップしたものみたいですね。

要約するとSassはSCSSフォーマットをサポートしており、SCSSはCSSを拡張する形で新機能を追加したフォーマットですが、新しい構文を導入しているわけではありません。そのため、SCSSは既存のCSSファイルと完全に互換性があり、既存のプロジェクトに簡単に組み込むことができます。例えば、Railsのアセットパイプラインでは、SCSSファイル(.scss拡張子)を自動的にSassプリプロセッサを使用して処理し、ブラウザで使用するために最適化します。このプロセスを通じて、Bootstrapなどのフレームワークの利点を活用しながら開発が行われます。

Bootstrapにも対応している優れものってことですね。

ネスト
スタイルシート内に共通のパターンがある場合は、要素をネストさせることができる

.center {
  text-align: center;
}

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

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

本来CSSの感覚って毎回{}を閉じて命令定義してたのですがそれをやらず;と改行をすることでできちゃうんですね。この最適化のことをネストと呼ぶと解釈しました。

#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を持つ要素のスタイル定義において、ロゴ自体のスタイルとマウスポインタが要素上にある際のホバー状態のスタイルが設定されています。SCSSでは親セレクタを参照するためにアンパサンド(&)記号が使われることが示されています。これにより、#logoが二度記述されることなく、ホバー属性のスタイルを効率的にネストすることが可能です

私なりの要約をすると
この場合マウスホバーするために改めて区切ってますが &を使うことによって

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

このようにつなげることができます。 これはすごいですね。

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のsccsをネストするとこのように合体もできる。
慣れの問題もありますがこうやって簡略化していくのがRailsの姿のようです。

変数
Sassでは、冗長なコードを削除し、より自由な表現を可能にするために、変数が定義できるようになっている。

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

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

$light-gray: #777;

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

なるほど。事前に変数を定義してcolorの部分で定義した変数をあてることで
より柔軟にSCCSとして適用するってことですね。

更にbootstrapのgemを入れとけばbootstrapで定義していた変数をいれるだけで
自在に呼び出せるってわけですね。

ネスト変数を書き直した結果、コードがみやすくなったというものが下記です。

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

5.1.2BootstrapとカスタムCSS

'#'で代用していたリンクを書き換えます
RailsではHTMLで記述も許されています。
<a href="/static_pages/about">About</a>

しかしRails流ではないので下記の形に変更します。

<%= link_to "About", about_path %>
Railsでは次のようなコードでは名前付きルーティングになっているようです。

そもそもが/static_pages/がrootになっていて
その中でAbout=about_pathになってるんですかね?

スクリーンショット 2024-04-19 14.47.14.png

もう少し次を通してみていきます。

5.3.1Contactページ

test/controllers/static_pages_controller_test.rb
require "test_helper"

class StaticPagesControllerTest < ActionDispatch::IntegrationTest

.
.
.

  test "should get contact" do
    get static_pages_contact_url
    assert_response :success
    assert_select "title", "Contact | Ruby on Rails Tutorial Sample App"
  end
end

だいぶコードが読めるようになってきました。
contactページのURL取得に成功したらtitleを確認するって形で解釈してます。

rails testを行なっても何も設定ないのでエラーがでます。

config/routes.rb
Rails.application.routes.draw do
.
.
.
  get  "static_pages/contact"
end

そこでrouteをgetで設定します。

app/controllers/static_pages_controller.rb
class StaticPagesController < ApplicationController
  .
  .
  .
  def contact
  end
end

次にcontlrollerを設定します。
ここではdefにcontactを追加します。
またStaticPagesControllerは Application Controllerの内容を継承しています。

app/views/static_pages/contact.html.erb
<% provide(:title, 'Contact') %>
<h1>Contact</h1>
<p>
  Contact the Ruby on Rails Tutorial about the sample app at the
  <a href="https://railstutorial.jp/contact">contact page</a>.
</p>

続いてContactページの作成を行います。
これでrails testを行なっても成功するようになります。

一つ一つこうやって確認するとどういう流れで動いてるのか
どこでデータを参照しているのかというのがわかりやすいですね。

RailsのルートURL

今度はルート設定の表記を最適化していくようです。

Railsチュートリアルでは一般的な規約に従い、基本的には_path書式を使い、リダイレクトの場合のみ_url書式を使うようにします。これはHTTPの標準としては、リダイレクトのときに完全なURLが要求されるためです。ただしほとんどのブラウザでは、どちらの方法でも動作するとのこと。

get "static_pages/help"
     ↓
get "/help", to: "static_pages#help"
このように切り分けることができ、どのディレクトリにあるのかをto: #変数で表示することができる

これでhelpにまつわるアクションが動作するようになる。

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

このように書き換えることができる。
まず/static_pages/home が URLの / root(TOPページ)にくるようになっている。
その他/help などの各アクションを取得する動きがこちらのroutesデータに記述されている。

test/controllers/static_pages_controller_test.rb
require "test_helper"

class StaticPagesControllerTest < ActionDispatch::IntegrationTest

  test "should get home" do
    get static_pages_home_url
    assert_response :success
    assert_select "title", "Ruby on Rails Tutorial Sample App"
  end

  test "should get help" do
    get static_pages_help_url
    assert_response :success
    assert_select "title", "Help | Ruby on Rails Tutorial Sample App"
  end

  test "should get about" do
    get static_pages_about_url
    assert_response :success
    assert_select "title", "About | Ruby on Rails Tutorial Sample App"
  end

  test "should get contact" do
    get static_pages_contact_url
    assert_response :success
    assert_select "title", "Contact | Ruby on Rails Tutorial Sample App"
  end
end

このtestコードを新しくしたのが下記になる。

test/controllers/static_pages_controller_test.rb
require "test_helper"

class StaticPagesControllerTest < ActionDispatch::IntegrationTest

  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
end

さっきの変更でroot_pathが使えるようになった為アップデートした。

この辺は型の流れがこうなっているので最終系としては現状こうだ
という解釈がよさそうですね。より効率的に綺麗にコードを見せる為にはどうしたらいいのか
実践はすべてが綺麗な効率化っていうわけでもないはずなので、この辺を読み解いていかなければいけないのかなと思ってます。

むずかしー。

5.3.3名前付きルーティング

<%= link_to "About", '#' %>

<%= link_to "About", about_path %>
に置き換えられます。

ルートを定義することによって2番目の引数に名前をつけることができました。

app/views/layouts/_header.html.erb
<header class="navbar navbar-fixed-top navbar-inverse">
  <div class="container">
    <%= 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>
    </nav>
  </div>
</header>

その結果がこうなりました。

5.3.4リンクのテスト

次にリンクのテストです。

これはWEBディレクター時代に経験があるのですが、プログラミング知識なしだと
どうしても手動でページが繋がるのかどうか確認をとってしまい、今なにやってたっけ?というのが
デバッグ時にザラにあります。
なのでこの作業は大変目から鱗ですね....

「統合テスト(Integration Test)」を使って一連の作業を自動化してみましょう。統合テストを使うと、アプリケーションの動作を端から端まで(end-to-end)シミュレートしてテストすることができます。

すごい便利なので楽しみです。

$ rails generate integration_test site_layout

まずはファイル生成をします。

(引用)
今回の目的は、アプリケーションのHTML構造を調べて、レイアウトの各リンクが正しく動くかどうかチェックすることです。

・ルートURL(Homeページ)にGETリクエストを送る。
・正しいページテンプレートが描画されているかどうか確かめる。
・Home、Help、About、Contactの各ページへのリンクが正しく動くか確かめる。

とのこと。

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を指定することにより
リンクが生きてるのか調べるようです。

count:2はrouteの画像ロゴとナビゲーションバーにあるので2回あるか確認をするとのこと。
よくできてますね。

assert_selectでいろいろチェックできるようです。
これはエラーがでたりしたら必要に応じてやるくらいに留めておきます。

$ rails test:integration
そうしたらintegrationの範囲をrails testして終わりのようです。

なるほどね。

5.4.1Usersコントローラ

今度は2番目のコントローラであるUsersコントローラを作成
(今頃気づいたんですがstatic_controllerって最初のコントローラーって意味だったんですね...)
rails generate controller Users new

app/controllers/users_controller.rb
class UsersController < ApplicationController

  def new
  end
end
app/views/users/new.html.erb
<h1>Users#new</h1>
<p>Find me in app/views/users/new.html.erb</p>
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

というわけで新規ユーザー用のコントローラができました。

5.4.2ユーザー登録用URL

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

続いてテストページも調整

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="https://railstutorial.jp/">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.svg", alt: "Rails logo", width: "200"),
                      "https://rubyonrails.org/" %>

リンクページを作成

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>

SignUPページを作成で完成

本章まとめ

・HTML5を使ってheaderやfooter、logoやbodyといったコンテンツのレイアウトを定義した
・Railsのパーシャルは効率化のために使われ、別ファイルにマークアップを切り出すことができる
・CSSは、CSSクラスとidを使ってレイアウトやデザインを調整する
・Bootstrapフレームワークを使うと、いい感じのデザインを素早く実装できる
・SassとAsset Pipelineは、開発効率のために切り分けられたCSSの冗長な部分を圧縮し、本番環境に最適化した結果を出力する
・Railsのルーティングでは自由にルールを定義することができ、また、その際に名前付きルーティングも使えるようになる
・統合テストは、ブラウザによるページ間の遷移を効率的にシミュレートする

感想

この章を通してどのようにモデルを作成するのかがわかった
またbootstrapはなぜ便利なのかも理解でき、こうやって工数を減らしているのかと
HTMLCSS学習した身からしたら目から鱗だった。
引き続き学習していきたい

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?