【Rails】application.html.erbのレイアウトの使い方と使わない方法

2018年4月20日

今日はRailsプログラミングの調べ物をしました。
テックアカデミーの掲示板で質問すればすぐ答えは得られると思いますが、自力で解決できそうと思いまして。

やりたいことは

・「application.html.erb」を読まずに表示する方法
・タイトルタグやメタタグをページごとに変える方法

この2つです。applicationレイアウトの整理をしつつ各方法を書いていきます。

application.html.erbには何が書いてあるか?

Railsではコントローラーのアクションを経由してHTMLファイルを読み込み表示する時に必ずviews/layouts/application.html.erbを読みます。

なのでapplication.html.erbの中に以下のように記述してあります。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>俺のRailsプログラミング</title>
    <%= csrf_meta_tags %>

    <!-- Bootstrap CSS-->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

    <!-- app/assets/stylesheets -->
    <%= stylesheet_link_tag  'application', media: 'all', 'data-turbolinks-track': 'reload' %>

    <!-- app/assets/javascripts-->
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>

    <!-- Bootstrap JavaScript-->
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    
    
  </head>

  <body>

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

bodyタグの下がコンテンツになりますが、yieldというメソッドを呼んでいます。

それで各ページに記述した内容がこのyieldに埋め込まれてブラウザの画面に表示される形です。

イメージとしては、全ページ共通でこのapplication.html.erbで枠を作って、yieldの部分だけ各個別ページのオリジナルのコンテンツや記事が入ってくるイメージです。

ただしこのままapplication.html.erbを使っていると、記事毎のタイトルタグの部分~~が全てのページで「俺のRailsプログラミング」になってしまいます。これは具合が悪い。

各ページでタイトルを変更する方法

全ページが同じタイトルだとおかしなサイトになってしまいます。SEO的にもよろしくない。なので各ページ毎にタイトルを用意しますのでapplication.html.erbのtitleタグの部分を以下のように修正します。

<title><%= page_title %></title>

ここではpage_titleというメソッドを呼ぶようにしています。ビュー側で新たに定義するメソッドはヘルパーに記述する慣習がありますので/app/helpers/application_helper.rbを修正しpage_titleメソッドを定義します。

module ApplicationHelper
  
  def page_title
    title = "俺のRailsプログラミング" #これがサイトのブランド名
    title = @page_title + " | " + title if @page_title
    title
  end

1行目ではサイトのトップページのタイトルを定義して代入しています。一般的にはサイトのブランド名を設定すると良いでしょう。

理想的なタイトルの付け方を伝授

私はどちらかというとSEOのほうが専門なのでここで小話を。

※このようなトップページタイトルの付け方が望ましいとされています。

ブランド名 | サイトの説明

例)
俺のRailsプログラミング | 初心者が一念発起してプログラマを目指すブログ

真ん中の|はパイプと呼びます。半角スペース パイプ 半角スペースとします。パイプじゃなくて半角のハイフン – でも構いません。日本ではパイプが主流で海外だとハイフンが多い気がします。

で、個別ページ(下層ページ)は以下のようなタイトルの付け方をすると良いでしょう。

個別ページのタイトル | ブランド名

例)
Railsで挫折しない心構え5つ | 俺のRailsプログラミング

で、Railsでもこの名付け方にならって先程のpage_titleメソッドを定義しました。

@page_titleというのは、個別ページ内で定義する個別ページのタイトルです。

なので例えばshow.html.erbの出だしで以下のように@page_titleを定義します。

<% @page_title = 'Railsで挫折しない心構え5つ' %>

これで個別ページごとにタイトルを設定することができるようになりました。

ヘッダーやヘッダー画像やフッターを作る

僕はこのように呼んでいますが、Railsの世界ではナビバーとかカバーとか言うのかもしれない。

要はヘッダーはサイトの画面上部のメニューとか画像の共通部分。ココにメニューがあるとグローバルメニューと言ったりする。

フッターは皆共通に知ってる画面最下部の部分を呼ぶ。

application.html.erbに、共通化できる部分を入れます。現状僕のapplication.html.erbは以下のようになっています。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title><%= page_title %></title>
    <%= csrf_meta_tags %>

    <!-- Bootstrap CSS-->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <!-- app/assets/stylesheets -->
    <%= stylesheet_link_tag  'application', media: 'all', 'data-turbolinks-track': 'reload' %>

    <!-- app/assets/javascripts-->
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>

    <!-- Bootstrap JavaScript-->
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    
    <!-- slick photo slideshow -->
    <%= yield :header %>
    
  </head>

  <body>
    <%= render 'layouts/navbar' %>

    <%= yield :cover %>

    <div class="container">
      <%= render 'layouts/flash_messages' %>

      <div class="row">
        <!-- 左コンテンツ -->
        <div class="col-md-9 left-contents">
                  <%= yield %>
        </div>
      
        <!-- 右サイドメニュー -->
        <div class="col-md-3">
            <%= render 'layouts/side_menu' %>
        </div>
      </div>
    </div>
      
    <%= render 'layouts/footer' %>
    
  </body>
</html>

新たに出てきたのがこれら。

    <%= yield :header %>
    <%= render 'layouts/navbar' %>
    <%= yield :cover %>
    <%= render 'layouts/side_menu' %>
    <%= render 'layouts/footer' %>

1行目は個別ページごとにheadタグ内部に入れたいものがあれば、ここに記述します。メタタグとかの記述はここ。
2行目はナビバーを用意して読み込んでいます。ナビバーにはサイトのロゴ画像とか、ログインボタン等があります。
3行目はここにヘッダー画像やH1タグを読み込んでいます。またSEOの話ですがH1タグもページごとに違って当たり前なので、個別ページ毎に設定しますからyieldを使っています。
4行目はここでサイドメニューを表示しています。
5行目がフッターですね。メニューとかコピーライトとかを記述します。

そうすると個別ページは以下のようにします。

<% @page_title ='Railsで挫折しない心構え5つ' %>

<% content_for :header do %>
	<meta name="keywords" content="Rails,プログラミング" />
	<meta name="description" content="このページではRails歴3年の私がRailsプログラミンで重要な考え方をご紹介します。" />
</div>

<% content_for :cover do %>
  <img src ="">
  <h1>Railsで挫折しない心構え5つをご紹介!</h1>
<% end %>

<h2>はじめに</h2>
<p>Railsを3ヶ月学習してきて‥</p>
‥
‥


このようにして枠に当てはめていきます。

application.html.erbを使いたくない場合

まるっきりapplication.html.erbの枠にはめたくない場合はコントローラーのアクションに以下のように記述する必要があります。

  def index
    #indexの中身記述
    # :
    # :
    
    render layout: false #application.html.erbを適用したくない
  end

これで飛んだ先のindex.html.erbファイルは全部書かないといけなくなりますが。

自分がいま作成中のWEBアプリはトップページは1カラムで、個別ページは2カラムでやりたいと思っているのでこのようにしています。