[Rails]初学者がform_withの流れを整理・理解するための記事


はじめに

Rails学習初期に、form_withの流れが理解できなかったのでまとめます。
Rails5.2.4です。

先にまとめ

「早くまとめろよ!」という方もおられるかと思いますので、先に流れをまとめます。

簡単に解説

UserモデルとPostモデルがある状況です。

①newアクションで、ビューページ(new.html.erb)を表示
newアクションを呼び出すリクエストが出されたら、まずはpostの新規投稿(new)ページが表示される
※イメージ

②newアクションで生成している@postインスタンスをビューに渡す

post_controller.rb
class PostsController < ApplicationController
~~
  def new
    @post = Post.new #ここで生成されている@postが、new.html.erbに渡される
  end
~~

③インスタンスのプロパティに値を入力してsubmit

④createアクションを呼び出す
上記の画像のように、投稿するボタン(form_withのsubmit)をクリックすると、form_withがcreateアクションを呼び出してくれます。

※form_withヘルパーメソッドは、渡されたインスタンス(この場合は@post)のプロパティを見て、createに飛ばすかupdateに飛ばすかを判断してくれる便利な子です。

form_withが考えてること
- @post が空 → 初めて作るんだな!じゃあcreate!
- @post が空じゃない → 変更したいんだな!じゃあupdate!

⑤post_paramsメソッドを呼び出す

post_controller.rb
class PostsController < ApplicationController
~~
  def create
    #createアクションが呼び出され、Post.create(post_params)が実行される→ post_paramsが呼び出される
    Post.create(post_params) 
    redirect_to root_path
  end

  private
  def post_params 
    params.require(:post).permit(:title, :content).merge(user_id: current_user.id)
  end
~~

⑥paramsで受け取った値のうち、permitで受け取る値を指定(許可)

paramsで受け取る値の状態
[1] pry(#<PostsController>)> params
=> <ActionController::Parameters {"utf8"=>"✓", "authenticity_token"=>"oLGgLMTcqSPi7cbK9j1wFhH5rqiwXYO7GyRoZcZFZe6Y5VdbHrWCOyeo37kgW/bsl+eANQrz7p/lAzZMnAS8Gg==", 
"post"=>{"title"=>"今日学んだこと", "content"=>"form_withは賢い子!"}, 
"commit"=>"投稿する", "exept"=>:index, "controller"=>"posts", "action"=>"create"} permitted: false>

見にくいので本来ない位置で改行していますが、通常は1行で返ってきます。

"post"=>{"title"=>"今日学んだこと", "content"=>"form_withは賢い子!"},
post_paramsで扱う値です。

permitで受け取る値を許可しておかないと、意図しない値がテーブルに保存される可能性があるので、指定がほぼ必須です。

⑦post_paramsの値でPostをcreateする(成功すればテーブルに保存される)
post_paramsメソッドで返された値で、Post.createすることになるので、
実質下記と同じ状態です。

  def create
    Post.create(title: "今日学んだこと", content: "form_withは賢い子!", user_id: 1) 
    redirect_to root_path
  end

この流れを確認した上で、もう一度冒頭の画像を見ると理解が深まると思います!

おわりに

form_tag、form_forとの違いはこちらの記事にまとめています。
[Rails]hamlでのform_with/form_for/form_tagの書き方

間違い等ありましたらご指摘いただけると幸いです。