0. 問題の概要
リクエスト送信時の画面表示方法として、処理に成功した際にはredirect_to
を使い、処理に失敗した際はrender
を使用することが一般的です。
redirect_to
とrender
の違いについて、こちらの方の記事を参考にしました。
https://qiita.com/koki_73/items/78b8cb2bde7930d55194
しかし、renderで画面表示した際に、URLが変わってしまうという問題があります。
この記事では、この問題に直面した際の解決策について説明しています。
0-1. 実装例
例として、posts_controllerのcreateアクションを実装するとします。
投稿に成功した場合はredirect_to
で画面遷移をし、投稿に失敗した場合はフラッシュメッセージを表示させ、render
でnew画面を再描画します。
def create
@post = current_user.posts.build(post_params)
if @post.save
# 途中の処理を省略
flash[:sucess] = "投稿しました!"
redirect_to sample_path(@post)
else
flash.now[:alert] = "投稿に失敗しました"
render :new
end
end
また、ビューファイル(new.html.erb)は以下のように記述する。
# 途中の処理を省略
<%= form_with url: post_sample_path, method: :post do %>
# 以下の処理を省略
<%= end %>
また、ルーティングは以下のとおりです。
new_post_sample_path GET /post/sample/new(.:format) post/sample#new
post_sample_path POST /post/sample(.:format) post/sample#create
以上のように実装することで、投稿が失敗すると、フラッシュメッセージを表示させるとともに、new画面が表示されます。
しかし、フラッシュメッセージが表示された後のnew画面でリロードを行うと、ルーティングエラーまたは別画面が表示されてしまいます。
1. 解決策
結論から言うと、new.html.erb
のフォーム部分でpostリクエストを指定しているため、createアクションのrender :new
で画面を再描画した際に、POSTリクエストのURLが表示されてしまうことが原因でした。
1-1. redirect_toを使う
def create
@post = current_user.posts.build(post_params)
if @post.save
# 途中の処理を省略
flash[:sucess] = "投稿しました!"
redirect_to sample_path(@post)
else
flash[:alert] = "投稿に失敗しました"
redirect_to new_post_sample_path(@post)
end
end
render
からredirect_to
に変更することで、URLが変わってしまう問題が解決する。
しかし、redirect_to
でURLを指定することで、入力した情報が保持されず、初期化されてしまうという新たな問題も発生してしまった。
その場合の解決策についてはこちらの方の記事にありました。
https://qiita.com/yuyasat/items/49e3296f3c64fccc7811
2. まとめ
リクエスト送信時の画面表示方法をrender
からredirect_to
に変更することで以下の問題を修正することができました。
フラッシュメッセージが表示された後のnew画面でリロードを行うと、ルーティングエラーまたは別画面が表示されてしまう
しかし、入力していた情報が消えてしまうという新たな問題も発生してしまいました。
この新たな問題については、今後考えていきます。