こんにちは、かつコーチです。
Railsでコントローラまで作れるようになると、次にぶつかる壁が「ビュー」です。
<%= %> と <% %> の違いがよくわからない。
application.html.erb に書いた内容がなぜか各ページに反映される。
このあたりでつまずく人がとても多いです。
この記事では、ERB(Embedded Ruby、HTMLの中にRubyコードを埋め込める仕組みです)の基本構文と、Railsのレイアウト機能である yield の仕組みを、実際に手を動かしながら解説します。
読み終わるころには、ビューファイルを自信を持って編集できるようになっているはずです。
ERB(Embedded Ruby)の基本構文
<%= %> と <% %> の違い
ERBには2種類のタグがあります。
この2つの違いを理解することが、ビュー学習の第一歩です。
<%= %>:Rubyの式(値を返す処理です)を実行し、その結果を画面に出力する<% %>:Rubyの処理は実行するが、結果は画面に出力しない
具体例で見てみましょう。
<%# app/views/posts/index.html.erb %>
<h1>投稿一覧</h1>
<% @posts.each do |post| %>
<div class="post">
<h2><%= post.title %></h2>
<p><%= post.body %></p>
</div>
<% end %>
@posts.each do |post| の部分は繰り返し処理そのものです。
これは画面に文字として表示したいものではありません。
そのため <% %> を使います。
一方 post.title はタイトルの文字列を取得する式です。
この値を画面に表示したいので <%= %> を使います。
つまずきポイント:= を忘れると何も表示されない
私が初めてRailsを触ったとき、一覧画面のタイトルが全く表示されずに焦った経験があります。
原因は単純で、<%= post.title %> と書くべきところを <% post.title %> と書いていました。
エラーは出ません。
ただ、画面には何も表示されないだけです。
これはRailsのエラーメッセージが出ない分、初心者には原因がわかりにくいトラブルです。
「値を表示したいときは = を必ずつける」と覚えておいてください。
application.html.erbでの共通レイアウト
レイアウトファイルとは
Railsでは app/views/layouts/application.html.erb が、すべてのページに共通するレイアウト(HTMLの骨組み:ヘッダーやフッター、<head> タグなど、全ページ共通の部分です)を管理しています。
デフォルトでは以下のような内容になっています。
<%# app/views/layouts/application.html.erb %>
<!DOCTYPE html>
<html>
<head>
<title>MyApp</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_importmap_tags %>
</head>
<body>
<%= yield %>
</body>
</html>
このファイルにヘッダーやナビゲーションを追加すると、全ページに共通して反映されます。
<%# app/views/layouts/application.html.erb(一部抜粋) %>
<body>
<header>
<nav>
<%= link_to "トップ", root_path %>
<%= link_to "投稿一覧", posts_path %>
</nav>
</header>
<main>
<%= yield %>
</main>
<footer>
<p>© 2026 かつコーチ</p>
</footer>
</body>
yieldの仕組み
<%= yield %> の部分に注目してください。
ここには、コントローラのアクションに対応した個別のビュー(例えば posts/index.html.erb)の内容が差し込まれます。
つまりRailsのビュー表示は、以下のような2段階の仕組みになっています。
- 各アクション用のビュー(
index.html.erbなど)がHTMLの中身を作る - その中身が
application.html.erbのyieldの位置に埋め込まれる
このおかげで、ヘッダーやフッターを毎回書かずに済むわけです。
レイアウトを個別に切り替える
管理画面用など、共通レイアウトを使いたくない場合は、コントローラ側で指定できます。
# app/controllers/admin/dashboard_controller.rb
class Admin::DashboardController < ApplicationController
layout "admin"
def index
end
end
この場合、app/views/layouts/admin.html.erb を用意しておけば、そちらが使われます。
よくあるつまずきポイント・エラー対処
パーシャル未使用で同じコードを繰り返してしまう
繰り返し使うHTML部品を毎回書いてしまうのは、初心者にありがちなパターンです。
❌ Before:同じコードを複数のビューにコピペしている
<%# app/views/posts/index.html.erb %>
<% @posts.each do |post| %>
<div class="post-card">
<h2><%= post.title %></h2>
<p><%= post.body %></p>
</div>
<% end %>
<%# app/views/posts/show.html.erb(似たカードを別ページでも書いてしまう) %>
<div class="post-card">
<h2><%= @post.title %></h2>
<p><%= @post.body %></p>
</div>
このやり方だと、カードのデザインを変更したいときに複数ファイルを直す必要があり、修正漏れが起きやすくなります。
✅ After:パーシャル(_post.html.erb)に切り出す
<%# app/views/posts/_post.html.erb %>
<div class="post-card">
<h2><%= post.title %></h2>
<p><%= post.body %></p>
</div>
<%# app/views/posts/index.html.erb %>
<%= render partial: "post", collection: @posts %>
<%# app/views/posts/show.html.erb %>
<%= render @post %>
パーシャル(_から始まるファイル名で共通化するビューの部品です)に切り出すと、修正が1箇所で済み、コードの見通しも良くなります。
NoMethodError: undefined method でハマる
私が実際に遭遇したエラーです。
一覧ページで @posts を渡し忘れたまま <% @posts.each do |post| %> と書いてしまい、以下のエラーが出ました。
NoMethodError in Posts#index
undefined method `each' for nil:NilClass
❌ Before:コントローラでインスタンス変数を用意していない
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
def index
# @postsを定義し忘れている
end
end
✅ After:アクションでインスタンス変数を定義する
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
def index
@posts = Post.all
end
end
@posts のように @ がついた変数はインスタンス変数と呼ばれ、コントローラからビューへ値を渡すために使われます。
ビュー側でエラーが出たときは、まずコントローラ側で変数が正しく定義されているかを確認する癖をつけましょう。
まとめ
この記事のポイント
<%= %>は値を出力し、<% %>は処理だけを行う=の付け忘れはエラーにならず、画面に何も出ないだけなので気づきにくいapplication.html.erbのyieldに、各アクション用ビューの内容が差し込まれる- 繰り返すHTMLはパーシャルに切り出して共通化する
- ビューでエラーが出たら、まずコントローラのインスタンス変数を疑う
次に読むべき記事
- コントローラの基本:アクションとストロングパラメータ
- RESTfulなルーティング設計(resources)の考え方
タグ: Ruby on Rails, 初心者向け, フレームワーク基礎