はじめに
通常、Railsでアンカー付きのリクエストを発生させるにはredirect_to
を使います。
redirect_to root_path(anchor: 'target')
では、render
でビューを表示させるときにアンカーを指定したいときはどうすればいいのでしょうか。render
はredirect_to
のような書き方はできません。
# 以下の書き方はできない
render :index(anchor: 'target')
render "index#target"
render
とredirect_to
の使い方やその違いについては以下の記事を参照してください。
アンカー指定が必要なケース
そもそも、render
でアンカー指定が必要なケースとはどのようなものでしょうか。よくあるのは、フォーム送信時にバリデーションエラーで元のページを再レンダリングするときです。
contact_controller.rb
class ContactsController < ApplicationController
def sending
@contact = Contact.new(contact_params)
if @contact.valid?
ContactMailer.send_mail(@contact).deliver_now
redirect_to contact_done_path
else
render :index
end
end
private
def contact_params
params.require(:contact).permit(:name, :email, :content, :confirm)
end
end
render
の部分を抜き出すと以下になります。
contact_controller.rb (抜粋)
if @contact.valid?
ContactMailer.send_mail(@contact).deliver_now
redirect_to contact_done_path
else
render :index
end
バリデーションチェックの結果が真の場合はメールを送信し送信完了ページにリダイレクトしています。一方、バリデーションチェックの結果が偽の場合、フォームを設置しているページを再レンダリングしています。再レンダリングしたページでは@contact.errors
に格納されているエラーメッセージを使用するため、redirect_to
ではなくrender
を使う必要があります。
このとき、フォームをページ下部に設置している場合、再レンダリングでページ先頭に戻されるのはユーザーフレンドリーな設計とは言えません。ページ先頭ではなくフォームの先頭に再レンダリングしたいと考えるのが普通です。
レンダリングでアンカー指定
結論から言うとrender
でアンカー指定することはできません(render
はビューをレンダリングするだけでURLの変更は行わないため)。代わりにフォーム送信時のURL指定時にアンカーを指定します。
index.html.erb
<%= form_with model: @contact, url: contact_sending_path(anchor: 'form') id: 'form' do |form| %>
<%= form_with model: @contact, url: '/contact/sending#form' id: 'form' do |form| %>
index.html.slim
= form_with model: @contact, url: contact_sending_path(anchor: 'form') id: 'form' do |form|
= form_with model: @contact, url: '/contact/sending#form' id: 'form' do |form|
render
は新しいURLのリクエストを作成するわけではないので、フォーム送信時に指定したURLが再レンダリング後のページでも使用されます。当然、そのURLにアンカーが指定されているなら再レンダリング後のページでも機能します。
ちなみに、バリデーションチェックの結果が真の場合にリダイレクトされるURL、つまり送信完了ページのURLにもフォームで指定したアンカーが残りますが、送信完了ページに該当のID(今回は#form
)が含まれない場合はアンカーは無視されます。ただし、表示されているURLはアンカー付きのままなので(/contact/done#form
)、それが気になるならJavaScriptで削ってください。
まとめ
Railsの機能というより裏ワザ的なテクニックなので、知っている人はあまり多くないかもしれません。render
でアンカー指定する機会はあまりないかもしれませんが、知っておくとよりユーザーフレンドリーな設計のWebアプリにできるかと思います。
本記事を参考にしていただければと思います。