Hit the books!!

プログラミング学習記録

「Ruby on Rails6 実践ガイド」勉強メモ(No.3)

「Ruby on Rails6 実践ガイド」を読むシリーズの続きです。

ud-ike.hatenablog.com

ud-ike.hatenablog.com

今日はChapter5の前半、レイアウトとかテンプレートの話です。

トップページ(仮)の作成

Baukis2の利用者別トップページを作成していきます。

ルーティングの設定

とりあえず、利用者ごとに以下のURLでアクセスできるようにする。

まずはroutes.rbを開いて、それぞれに名前空間を設定するnamespaceというメソッドを使用してルーティングを設定する。(ルーティングの詳細は別の章で)

# config/routes.rb

Rails.application.routes.draw do
  namespace :staff do
    root 'top#index'
  end

  namespace :admin do
    root 'top#index'
  end

  namespace :customer do
    root 'top#index'
  end
end

この結果、URLパスの先頭に含まれる文字列(staff/admin/customer)が特別な意味を持つようになる。

rootは、クライアント(ブラウザ)がルートURLにアクセスしたときに、どのアクションが処理を受け持つかを指定するメソッド。

root 'top#index'

root 'コントローラー名#アクション名'で記述されている。

コントローラーとアクションの作成

config/routes.rbで指定した3つのコントローラーを生成する。

 % bin/rails g controller staff/top
Running via Spring preloader in process 1696
      create  app/controllers/staff/top_controller.rb
      invoke  erb
      create    app/views/staff/top
      invoke  rspec
      create    spec/requests/staff/top_request_spec.rb

同様に他の2つも生成。

% bin/rails g controller admin/top
% bin/rails g controller customer/top

生成された3つのコントローラーについて、indexアクションを追加する。

# app/controllers/staff/top_controller.rb 

class Staff::TopController < ApplicationController
  def index
    render action: 'index'
  end
end

Rails用語のアクションとは、コントローラークラスのpublicなインスタンスメソッドを指す。

render action: 'index'

renderは、HTML文書を生成するメソッドである。この式は、標準パスにあるindexアクション用のERBテンプレート(app/views/staff/top/index.html.erb)を用いてHTML文書を作成せよ、という意味になる。

ERBテンプレートとはRubyを埋め込む仕組みのことで、ERBテンプレートのファイルには.erbという拡張子をつける。結果としてHTMLが作成されるのであれば、.html.erbのように二重に拡張子をつけるのが一般的。

原則としてERBテンプレートはapp/viewsディレクトリにコントローラーごとにわけて置き、ファイル名にはアクション名を使う。

なお、アクションの中で一度もクライアント(ブラウザ)にレスポンスを返すメソッド(render、redirect_to、send_file、respond_withなど)が呼ばれなかった場合、暗黙的にそのアクションに対応するERBテンプレートを用いてHTML文書が生成される。つまり、先ほどのrender action: 'index'という行は省略することができ、indexアクションは以下のように中身がなくても良い。

  def index
  end

ERBテンプレートの作成

app/views/staff/topディレクトリに新たにindex.html.erbを作成する。

# app/views/staff/top/index.html.erb

<% @title = '職員トップページ' %>
<h1><%= @title %></h1>

<%%>で囲まれた範囲はRubyコードとして解釈される。

ブラウザでhttp://localhost:3000/staffにアクセスすると、画面が表示されればOK。

% bin/rails db:createしないとDBがありませんってエラーが出るはず。

f:id:ud_ike:20201210100908p:plain

同様に、app/views/admin/top/index.html.erbとapp/views/customer/top/index.html.erbも作成し、管理者トップページと顧客トップページを表示させる。

レイアウト

作成したトップページのソースコードを確認すると、bodyタグやhtmlタグなどのERBテンプレートに記述した以外のことも含まれている。

これらはapp/views/layoutsディレクトリにあるERBテンプレートからきている。このERBテンプレートをレイアウトと呼ぶ。

デフォルトではapp/views/layoutsにapplication.html.erbというファイルがあるだけで、内容は次の通り。

# app/views/layouts/application.html.erb

<!DOCTYPE html>
<html>
  <head>
    <title>Baukis2</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

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

  <body>
    <%= yield %>
  </body>
</html>

<%= yield %>という部分にアクションで指定されたERBテンプレートが挿入され、レイアウトを含むHTML文書全体がブラウザに返されるようになっている。

また、stylesheet_link_tagはこのページに読み込むCSSファイルを指定するメソッドで、第1引数にはCSSファイルの名前を指定する。stylesheet_link_tag 'application'はapp/assets/stylesheetsディレクトリにあるapplication.cssが読み込まれることになる。

部分テンプレート

application.html.erbを次のようにカスタマイズする。

# app/views/layouts/application.html.erb

    :

  <body>
    <div id='wrapper'>
      <%= render 'shared/header' %>
      <div id='container'>
        <%= yield %>
      </div>
      <%= render 'shared/footer' %>
    </div>
  </body>
</html>

そして、app/viewディレクトリにsharedディレクトリを作成し、新規ファイル_header.html.erbを次の内容で作成する。

# app/views/shared/_header.html.erb

<header>
  <span class='logo-mark'>BAUKIS2</span>
</header>

さらに、app/views/sharedディレクトリに新規ファイル_footer.html.erbを作成し、以下の内容を記述する。

# app/views/shared/_footer.html.erb 

<footer>
  <p>&copy; 2020 Tsutomu Kuroda</p>
</footer>

ブラウザで確認すると、このように変化する。

f:id:ud_ike:20201210105129p:plain

レイアウトに加えた

<%= render 'shared/header' %>

<%= render 'shared/footer' %>

は、いずれもrenderメソッドによって部分テンプレートをレイアウトの中に埋め込んでいる。

部分テンプレートとは、他のERBテンプレートに埋め込まれるためのERBテンプレートで、ファイル名がアンダースコア(_)で始まるという規則がある。

ヘルパーメソッドの定義

ERBテンプレート(レイアウト、部分テンプレートも含む)の中で使用できるメソッドをヘルパーメソッドと呼ぶ。

ヘルパーメソッドは自分で定義することもできる。app/helperディレクトリにあるapplication_helper.rbでApplicationHelperのモジュールメソッドとして定義すればヘルパーメソッドになる。

次のように変更して、簡単なメソッドを作成してみよう。

# app/helpers/application_helper.rb

module ApplicationHelper
  def document_title
    if @title.present?
      "#{@title} - Baukis2"
    else
      'Baukis2'
    end
  end
end

レイアウトも変更する。

# app/views/layouts/application.html.erb

    :
<html>
  <head>
    <title><%= document_title %></title> # 変更
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    :
    :

ブラウザをリロードすると、タイトルバーに表示されているテキストが変わる。

f:id:ud_ike:20201210141353p:plain

感想

今回の内容自体は難しくなかったが、作業しているとDBに接続できなかったりエラーが起きた。 時間はかかったし最適解じゃないかもしれないけど、解決できて無事に動作確認ができたのがうれしかった。