基本

Ruby on Railsのレイアウトテンプレートを設定する

Ruby on Railsのレイアウトは、複数のページに共通するHTMLの枠組み(ヘッダー、フッター、ナビゲーションなど)を1つのファイルで管理する仕組みです。デフォルトではapplication.html.erbがすべてのページに適用されますが、コントローラーやアクションごとに異なるレイアウトを使用することも可能です。この記事では、レイアウトテンプレートの設定方法と活用テクニックを解説します。

基本的な使い方

Railsでは、app/views/layouts/application.html.erbがデフォルトのレイアウトファイルです。すべてのコントローラーのビューはこのレイアウト内に埋め込まれます。

app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>MyApp</title>
    <%= csrf_meta_tags %>
    <%= stylesheet_link_tag "application" %>
    <%= javascript_pack_tag "application" %>
  </head>
  <body>
    <header>共通ヘッダー</header>
    <main>
      <%= yield %>
    </main>
    <footer>共通フッター</footer>
  </body>
</html>

<%= yield %>の部分に、各ビューファイルの内容が挿入されます。ヘッダーやフッターなどの共通要素をレイアウトに記述しておけば、各ビューにはコンテンツ部分だけを書くことで済みます。

コントローラーごとにレイアウトを変更する

コントローラーにlayoutを指定すると、そのコントローラーのすべてのアクションで使用するレイアウトを変更できます。

app/controllers/admin_controller.rb
class AdminController < ApplicationController
  layout "admin"
  # app/views/layouts/admin.html.erbが使用される

  def dashboard
  end

  def settings
  end
end
app/views/layouts/admin.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>管理画面</title>
    <%= csrf_meta_tags %>
    <%= stylesheet_link_tag "admin" %>
  </head>
  <body class="admin-layout">
    <nav class="admin-sidebar">
      <!-- 管理画面用サイドバー -->
    </nav>
    <div class="admin-content">
      <%= yield %>
    </div>
  </body>
</html>

この例では、AdminControllerのすべてのアクションに対してadmin.html.erbレイアウトが適用されます。一般ユーザー向けと管理者向けで異なるデザインを適用するのに便利です。

アクション単位でのレイアウト変更

特定のアクションでのみ異なるレイアウトを使用したい場合は、renderメソッドのlayoutオプションを使います。

app/controllers/posts_controller.rb
class PostsController < ApplicationController
  def index
    @posts = Post.all
    # デフォルトのapplication.html.erbが使用される
  end

  def print_view
    @post = Post.find(params[:id])
    render layout: "print"
    # app/views/layouts/print.html.erbが使用される
  end

  def embed
    @post = Post.find(params[:id])
    render layout: false
    # レイアウトなし(ビューの内容だけが表示される)
  end
end

layout: falseを指定するとレイアウトが適用されず、ビューファイルの内容だけが出力されます。iframeでの埋め込みやAPI的な使い方をする場合に便利です。

content_forによる名前付きyield

content_forを使うと、ビューからレイアウトの特定の場所にコンテンツを挿入できます。ページごとに異なるCSSやJavaScriptを読み込む場合に活用します。

app/views/layouts/application.html.erb
<head>
  <title><%= content_for?(:title) ? yield(:title) : "MyApp" %></title>
  <%= yield :head %>
</head>
<body>
  <%= yield %>
  <%= yield :scripts %>
</body>
app/views/posts/show.html.erb
<% content_for :title, @post.title %>

<% content_for :head do %>
  <%= stylesheet_link_tag "posts" %>
<% end %>

<h1><%= @post.title %></h1>
<p><%= @post.content %></p>

<% content_for :scripts do %>
  <script src="/js/posts.js"></script>
<% end %>

yield :headの位置にcontent_for :headで定義した内容が挿入されます。content_for?(:title)でコンテンツが定義されているか確認し、未定義の場合はデフォルト値を使用できます。

ポイント

content_forはページタイトル、メタタグ、追加のCSS/JavaScriptなど、ページごとに変わるhead内の要素を管理するのに特に便利です。

注意

レイアウトの種類が増えすぎると管理が複雑になります。共通部分はパーシャルとして切り出し、レイアウトファイル自体はシンプルに保つことを心がけてください。

まとめ

  • app/views/layouts/application.html.erbがデフォルトのレイアウトファイル
  • <%= yield %>の位置にビューの内容が埋め込まれる
  • コントローラーにlayout "名前"で使用するレイアウトを指定できる
  • render layout: falseでレイアウトなしの出力が可能
  • content_forでビューからレイアウトの特定位置にコンテンツを挿入できる
  • 管理画面や印刷用など、用途に応じて複数のレイアウトを使い分ける