if it does't challenge you, it can't change you

RubyのWebエンジニアやってます。主にRuby on Railsのことで勉強になったこと書いていきます。

redirect_toとrenderの違い、renderの注意点

redirect_toはコントローラーのアクションを指定。

 

renderはコントローラーを通さず、ビューファイルを指定。

 

student/showファイルでBlog.newを作って、blogsテーブルに新しいレコード作成しようとする時に、バリデーションに引っかかってみる。

 

f:id:shoheimoment:20171203232342p:plain

 

バリデーションにひっかかったときはrenderでstudent/showに指定しているが、URIがblogsになりその上にrenderのビューファイル(students/show.html.erb)が反映される。

 

f:id:shoheimoment:20171203232424p:plain


※この時、最初と同じstudents/showファイルが表示されるが、students_controller#showで指定したインスタンス変数は反映されないので、blogs#createでまたインスタンス変数としてを設定してあげなければいけない。しかし、コントローラーが違うからparamsメソッドで取得する値によく注意しなければならず、同じコードでいいわけではない。適宜、修正が必要。

 

 

上記のrenderメソッドを理解していないとこういう疑問が生まれてくる。

新しい投稿画面から投稿確認画面にいくときに、下記のようなメソッドをform_withのurlに指定してあげてみる。

newからconfirm行くのはわかるけど、confirmからconfirmに行ったら無限ループに入って、ずっと投稿完了できないんじゃないの?

 

def choose_new_or_edit 
if
action_name == ‘new' || action_name == ‘confirm’ confirm_blogs_path #省略
end
end

 

new.html.erb

<%= form_with(model: @blog, local: true ,url: choose_new_or_edit ) do |form| %>
#省略
<% end %>

 

comfirm.html.erb

<%= form_with(model: @blog, url: blogs_path, local: true) do |form| %>
#省略
<% end %>

 

 

 これはnewからconfirmに行くけど、newからの入力がバリデーションでひっかかった場合、URIはconfirmのままnewにrenderされる。renderはそのベージにそのまま違うページの内容が貼り付けられてるようなイメージ。

blogs_controller.rb

def create
  @blog = Blog.new(strong_params)
  if @blog.save
    redirecto_to blogs_path
  else
    render 'new'
  end
end

 

f:id:shoheimoment:20171204183742p:plain

 

そして今度validationにひっかからないように入力すると、newからconfirmに行ってるように見えるが、confirmからconfirmに遷移している。

 

f:id:shoheimoment:20171204183813p:plain


これは検証でひっかかったからもう一回確認するためにこういう風になっている。
一度バリデーションでひっかかったconfirmから次はバリデーションにひっかからなければ、今度はconfirm viewのform_with設定されているurlに飛ぶから上のメソッドはもう適用されない.。なので、confirm→confirmに回り続けるような無限ループは起こらない。