6時だョ!!全員集合!!

Rails・JavaScrictを中心にアウトプットします。

2021年9月2日 現場Rails Chapter7(7-1-2 新規登録画面からの遷移先を変える)

form要素内のsubmitボタン

form要素内のsubmitボタンを押すと、以下の挙動が実行されます。

現場Rails P.289

form要素内のsubmitボタンが押されると、パラメータに、押されたボタンのname属性の値をキーとしてキャプションが格納されます。

例)

  f.submit '戻る', name: 'back' #=> params[:back]に'戻る'という文字列が格納されて、アクションへ渡されます。
  f.submit '登録' #=> params[:commit]に'登録'という文字列が格納されて、アクションへ渡されます。

commitパラメータ とは、どのボタンが押されたのか、サーバ側で判断できるように、デフォルトでついています。そのため、name属性の値を省略しても、commitで補っているのです。

redirect_to @taskについて

redirect_toメソッドは、以下のように省略して書けます。

redirect_to task_url(@task.id)

# リンクのパスとしてモデルオブジェクトが渡されると自動でidにリンクされるので、「.id」を省略出来ます。
redirect_to task_url(@task)

# URLヘルパーは省略出来ます。
redirect_to (@task)

# Rubyでは()は省略出来ます。
redirect_to @task

確認画面で戻るボタンを押した時、入力フォームに入れた値をどのように次の画面へ渡しているのか?(p291)

# app/views/tasks/confirm_new.html.slim
= form_with model: @task, local: true do |f|
  table.table.table.hover
    tbody
    # フォーム入力
        
  = f.submit '戻る', name: 'back', class: '# 省略'
  = f.submit '登録', class: '# 省略'

form_withの仕組み
↓画像引用:【Rails】form_with/form_forについて【入門】 フォームの"model:@task"の@taskに入った中身によってどのアクションを呼び出すのかを判断させています。上のフォームで戻るボタンを押した場合、confirm_newアクション側で定義した@taskがフォームに設定されているので、RailsがCreateアクションを呼び出す仕組みになっています。

# app/controllers/tasks_controoler.rb
class TasksController < ApplicationController

  # 〜〜〜 省略 〜〜〜
  def new
    @task = Task.new
  end

  def confirm_new
    @task = current_user.tasks.new(task_params)
    render :new unless @task.valid?
  end

  def create
    # 入力フォームの内容を元にタスクを作成後、@taskに代入
    @task = current_user.tasks.new(task_params)

    # =============================================
    # 「登録内容の確認」ページ(confirm_new.html.slim)で "戻る"を押す。
    # "戻る"を押すとparams[:back]に'戻る'という文字列が入る。
    # params[:back]に値が入っている場合、present?メソッドの戻り値がtrueになる。
    # 最初に定義した@taskがform_withヘルパーに設定されるので、
    # フォームに入力した情報がタスク新規登録画面に再度表示される。
    if params[:back].present?
      render :new
      return
      # returnが無いと以下のコードも実行してしまう。
    end
    # =============================================

    # *********************************************
    # 「登録内容の確認」ページ(confirm_new.html.slim)で"登録"を押す。
    # "登録"を押したので、params[:back]は存在しない。
    # そのため、上のif文が実行されずに終了する。
    # 上のif文が終了後、下のif文が正常に実行されると、タスクがDBに保存される。
    if @task.save
      redirect_to @task, notice: "タスク...登録しました。"
    else
      render :new
    end
    # *********************************************
  end

  # 〜〜〜 省略 〜〜〜
end

インスタンス変数(@task)は次のビューへ情報を渡すことが出来ます。renderをすることによって、インスタンス変数の情報を渡すことが出来るのです。ここで、redirect_toをしてしまうと再度ブラウザからリクエストを出してから画面遷移をするので、インスタンス変数の情報を渡せないため、注意が必要です。

returnを書く意味

 rubyではreturnを省略できるので、使い馴染みのないreturnが TasksController で使われている事に疑問を持ちました。今回の場合returnがないと次のif文である@task.saveまで処理が行われてしまいます。そしてrenderメソッドは同じアクションの中で2回以上呼び出されるとエラーになります。これを防ぐためにreturn を書いているわけですがrender :new and returnこのように and return と書くこともできます。 render また今回の例ではないがredirect_to の後の処理も実行されてしまう事を覚えておくとよいでしょう。

#新規登録画面(ビュー)

h1 タスク新規登録

# 省略
# @taskのところに、フォームに入力された値が入ってくる(インスタンス変数として)
= form_with model: @task, local: true, url: confirm_new do |f|
  .form-group
    #省略
    
  = f.submit'確認', class: #省略

redirect_toとrender挙動の違い

# インスタンス変数の値は次の画面に送られません。
redirect_to #=>(再度リクエストを出して)画面を遷移させます。

# インスタンス変数の値は次の画面に送られます。
render #=> 画面を遷移させます(リクエストを出さずに)
  • render     : controller → view
  • redirect_to   : controller → URL → route → controller → view

参照

redirect_to @userが何を省略しているかわかりますか?〜挫折しないRailsチュートリアル7章〜

https://qiita.com/Kawanji01/items/96fff507ed2f75403ecb

Rails】form_with/form_forについて【入門
https://qiita.com/snskOgata/items/44d32a06045e6a52d11c

Rails】renderとredirect_toの違いと使い分け
https://qiita.com/morikuma709/items/e9146465df2d8a094d78

Railsのutf8パラメータとcommitパラメータ
Railsのutf8パラメータとcommitパラメータ - koukiblog

pikawakaブログrenderメソッドを使うときの注意点

【Rails】 renderメソッドの使い方を徹底解説! | Pikawaka - ピカ1わかりやすいプログラミング用語サイト