Ruby on Railsでは、コントローラーのアクション名と同じ名前のビューファイルが自動的にレンダリングされます。しかし、renderメソッドを使うことで、デフォルトとは異なるビューテンプレートを明示的に指定して表示することができます。この記事では、renderメソッドの様々な使い方と実践的な活用方法を解説します。
基本的な使い方
Railsでは通常、アクション名に対応するビューが自動的に表示されます。例えば、indexアクションはindex.html.erbを表示します。
class PostsController < ApplicationController
def index
@posts = Post.all
# 自動的にapp/views/posts/index.html.erbが表示される
end
endこの自動的なビューの選択は「暗黙のレンダリング」と呼ばれます。Railsがアクション名からビューファイルのパスを推測して表示してくれるため、多くの場合はrenderを明示的に書く必要はありません。
別のビューを表示する
同じコントローラーのビューディレクトリ内にある別のビューを指定して表示するには、renderにビュー名を文字列で渡します。
class PostsController < ApplicationController
def index
@posts = Post.all
render "list"
# app/views/posts/list.html.erbが表示される
end
end上記の例では、indexアクションがデフォルトのindex.html.erbではなく、list.html.erbを表示します。拡張子(.html.erb)は省略して指定します。
シンボルを使って指定することもできます。
render :list
# render "list" と同じ別のフォルダのビューを表示する
異なるコントローラーのビューディレクトリにあるテンプレートを表示することも可能です。app/views/からの相対パスを指定します。
class PostsController < ApplicationController
def index
@user = current_user
render "users/dashboard"
# app/views/users/dashboard.html.erbが表示される
end
endこの機能は、複数のコントローラーで同じビューテンプレートを共有したい場合に便利です。例えば、管理者用と一般ユーザー用のコントローラーで同じダッシュボードビューを使いたい場合などに活用できます。
renderのオプション
renderメソッドには様々なオプションがあり、テキストやJSON、ステータスコードなどを返すことができます。
class PostsController < ApplicationController
# プレーンテキストを返す
def text_example
render plain: "Hello, World!"
end
# JSONを返す
def json_example
render json: { message: "成功", posts: @posts }
end
# ステータスコードを指定する
def not_found
render file: "#{Rails.root}/public/404.html",
status: :not_found,
layout: false
end
# HTMLを直接返す
def inline_example
render html: "<h1>直接HTMLを返す</h1>".html_safe
end
# レイアウトを変更する
def admin_page
render layout: "admin"
# app/views/layouts/admin.html.erbが使用される
end
endrender json:はAPIエンドポイントを実装する際によく使います。status:オプションでHTTPステータスコードを指定でき、シンボル(:not_found、:ok、:createdなど)で記述できます。
createやupdateでの活用
renderの最も一般的な使い方の一つが、バリデーションエラー時にフォームを再表示する場面です。
class PostsController < ApplicationController
def create
@post = Post.new(post_params)
if @post.save
redirect_to @post, notice: "投稿を作成しました"
else
render :new, status: :unprocessable_entity
# エラーメッセージ付きでフォームを再表示
end
end
def update
@post = Post.find(params[:id])
if @post.update(post_params)
redirect_to @post, notice: "投稿を更新しました"
else
render :edit, status: :unprocessable_entity
end
end
end保存に失敗した場合、redirect_toではなくrenderを使います。renderはHTTPリダイレクトを行わないため、@postに格納されたバリデーションエラー情報がそのままビューで使用でき、ユーザーにエラー内容を表示できます。
renderとredirect_toの違いを理解することが重要です。renderは現在のリクエスト内で別のビューを表示するだけで、URLは変わりません。redirect_toはブラウザに新しいリクエストを送らせるため、URLが変わります。
1つのアクション内でrenderを複数回呼ぶとエラーになります(AbstractController::DoubleRenderError)。条件分岐でrenderとredirect_toを使い分ける場合は、必ずreturnをつけるか、if/elseで排他的に記述してください。
まとめ
- Railsはアクション名に対応するビューを自動的にレンダリングする(暗黙のレンダリング)
render "ビュー名"で同じフォルダ内の別ビューを表示できるrender "フォルダ名/ビュー名"で別フォルダのビューを表示できるrender plain:、render json:でテキストやJSONを直接返せる- バリデーションエラー時は
redirect_toではなくrenderでフォームを再表示する - 1つのアクション内で
renderを複数回呼ぶとエラーになるので注意