rails-tutorial第5章


headタグの中身について

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>

<%= csrf_meta_tags %>はcsrf対策のコードでクラッキングからサイトを守る。

<%= stylesheet_link_tag    'application', media: 'all',
                               'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application',
                               'data-turbolinks-track': 'reload' %>

上記はcssに何か書かれていたら反映するよー。jsに何か書かれてたら反映するよーって意味。

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

上記はIEが9以下?の場合、HTML5のheaderタグなどが使えないため、JSでなんとかするよーってコード。

なんでaタグじゃなくてlink_toメソッドを使うの?

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

別に以下のコードでもよくね?って思うけど

<a href = # id = logo>sample app</a>

aタグだとhelperメソッドや変数を呼び出すことができないという欠点がある。

<%= link_to #{example}, static_pages_url, id: "logo" %>

そのため上記のようにurlや表示する文字にRubyのメソッドを使いたいがためにlink_toメソッドを使うのである。
id: logo はlink_toメソッドのオプションとしてハッシュの形で書かれている。
idは元から決められているがhogehoge: 'foobar'というオリジナルのオプションも与えられる。
オプション引数と呼ばれている。

Bootstrap

先に書いたnavbar や containerはbootstrapでもともと決められたクラス名。
ちなみにbootstrapは公式サイトからダウンロードする必要はなく、

gem 'bootstrap-sass', '3.3.7'

$bundle installで準備ok。

$ touch app/assets/stylesheets/custom.scss
でファイルを作り

app/assets/stylesheets/custom.scss
@import "bootstrap-sprockets";
@import "bootstrap";

を記入する。

image_tagについて

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

app/assets/images/に画像ファイルを置いておく(画像ファイルはここにダウンロードする)ことで、image_tagヘルパーによって画像を探してくれる。

ちなみにalt属性(オルト属性)とは、HTMLのimg要素の中に記述される画像の代替となるテキスト情報です。 ... 従って、そうした「画像が閲覧できない環境下でも、その情報が正しく理解される」ような代替テキスト情報がalt属性には記述されなければならないらしい。

パーシャルについて

yieldの時のように自分で自分のテンプレートを作りたい!そんなときに使うのがパーシャル。

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>

<%= render 'layouts/header' %>はヘッダーを別ファイルに分けて、「ヘッダーいじりたい人はlayouts/header見てねー」という感じになっている。これにより散らかったコードをdryにできる。

もちろん今までのコードを別ファイルにまとめる必要があるが、その際のファイル名はパーシャルとわかるように_から始まるファイル名にする。

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

つまり、<%= render 'layouts/shim' %>の場合は_shim.html.erbというファイル名にする。
逆に慣れてきたら最初からパーシャルを作ってコーディングしていけば早い。

アセットパイプラインとは

CSS JS imageなどの管理機能。

1.アセットディレクトリ

静的ファイルを目的別に分類する。

2.マニフェストファイル

1つのファイルにまとめる方法をrailsに指示する。

app/assets/stylesheets/application.css
*= require_tree .
*= require_self

1行目はマニフェストファイル(上記のファイル)内のcssの記述をまとめる。
2行目はマニフェストファイル以下のファイルもまとめるという意味。

3.プリプロセッサエンジン

指示に従いブラウザに配信できるように結合する。

foobar.js.coffee
foobar.js.erb.coffee
1行目の場合、coffee.script → JavaScriptの順で外側からコンパイルされる。

なぜアセットパイプライン?

パソコン的には複数のファイルを読み込むより、1つのファイルで改行や空白を無くしたものの方がレスポンスが早いから。また開発者的にも複数のファイルの方が開発がしやすく、それを一つにまとめてくれるなんて最高!ってこと。

名前付きルートについて

config/routes.rb
Rails.application.routes.draw do
  get 'static_pages/home'

  get 'static_pages/help'
  get 'static_pages/about'
  get 'static_pages/contact'
  root 'static_pages#home'
end

この状態だと、urlにいちいちstatic_pagesが出てきて、わかりづらい.
そもそも、上記は「このurlにリクエストされたらこのコントローラのこのアクションを実行してください」という情報を1つにまとめてしまっている。
もうちょっとわかりやすくできないものかと。

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

このように書き換えることによってヘルパーを使えるようになる。
例えば、/helpだったらhelp_path /aboutなら about_path
root なら root_pathという感じだ。これが名前付きルート。

名前付きルートをテストで使うと以下のようになる。

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

名前付きルートを使う注意点としては、使うときに''をつけないこと。urlをそのまま入れるときは''必要だけど、名前付きルートはそのまま書かないと逆にエラーになってしまう。

統合テスト (Integration Test)

統合テストは、ページから別のページに飛ぶなどurlがちゃんと機能してるか?を確かめるときに使う。
アプリケーションの動作を端から端まで (end-to-end) シミュレートしてテストすることができる。

$ rails generate integration_test site_layout

上記のコマンドでテストファイルができる。

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

上記はRailsは自動的にはてなマーク "?" をabout_pathに置換しています (このとき "about_path" 内に特殊記号があればエスケープ処理されます)。これにより、次のようなHTMLがあるかどうかをチェックすることができます。

<a href="/about">...</a>

一方で、ルートURLへのリンクは2つあることを思い出してください (1つはロゴに、もう1つはナビゲーションバーにあります)。このようなとき、

assert_select "a[href=?]", root_path, count: 2

上記のようにそのページにいくつ指定したurlリンクが存在するかもテストすることができる。

Users controller作ってみる。

$ rails generate 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でアクセスできるようにして、signup_pathという名前ルートも使えるようにする。コントローラーを作成すると、テストも自動作成されるよね。でも上記で名前付きルート設定しちゃったからテストが通らない。なので、、

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

名前付きルートを設定したら、必ずテストコードも書き換えるようにする。