💻

renderで画面表示するとURLが変わってしまう問題を解決する

に公開

問題の概要

リクエスト送信時の画面表示方法として、処理に成功した際にはredirect_toを使い、処理に失敗した際はrenderを使用することが一般的です。

redirect_torenderの違いについて、こちらの方の記事を参考にしました。
https://qiita.com/koki_73/items/78b8cb2bde7930d55194

しかし、renderで画面表示した際に、URLが変わってしまうという問題があります。
この記事では、この問題に直面した際の解決策について説明しています。

実装例

例として、posts_controllerのcreateアクションを実装するとします。
投稿に成功した場合はredirect_toで画面遷移をし、投稿に失敗した場合はフラッシュメッセージを表示させ、renderでnew画面を再描画します。

posts_controller.rb

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)は以下のように記述する。

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画面でリロードを行うと、ルーティングエラーまたは別画面が表示されてしまいます

解決策

結論から言うと、new.html.erbのフォーム部分でpostリクエストを指定しているため、createアクションのrender :newで画面を再描画した際に、POSTリクエストのURLが表示されてしまうことが原因でした。

redirect_toを使う

posts_controller.rb

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

まとめ

リクエスト送信時の画面表示方法をrenderからredirect_toに変更することで以下の問題を修正することができました。

フラッシュメッセージが表示された後のnew画面でリロードを行うと、ルーティングエラーまたは別画面が表示されてしまう

しかし、入力していた情報が消えてしまうという新たな問題も発生してしまいました。
この新たな問題については、今後考えていきます。

参考

https://qiita.com/koki_73/items/78b8cb2bde7930d55194
https://qiita.com/yuyasat/items/49e3296f3c64fccc7811

Discussion