(Rails) form_with modelではなくform_with urlを使いこなす

状況

投稿機能を作った際にcontrollerの中でindexとcreateの2つの部分でmodel名.newが使われていた。

また、全てのviewのアクションに対して、model名.newを用意するのが面倒である(before_action等を使えば防げるが...)

これは「rbの基本として、重複は避けるとある。」に反すると思い、回避できるのかを試してみた。

補足

indexのmodel名.newは「この箱に入れてください」という仮の箱を用意し、

createのmodel名.newは「仮の箱から取り出して正式な箱に入れてください」という感じ

結論

<%=form_with model:%>と<%=form_with url:%>を使い分けることで実現する。推奨ではない。

詳細

<%=form_with model:%>と<%=form_with url:%>の差

イメージとしてはもともとmodelの型(値を入れる箱)を作るか作らないかの差

そもそも <%=form_with model:%>と<%=form_with url:%>の違いはdbに保存するかどうかである。 簡単に言うとdbに保存する時に分かりやすくするかの違いである。

また、違いを別の言い方をすると、情報を送った時に2重のハッシュにするかどうかである。

投稿フォーム

view

# ココに<%=form_with ...%>が入る #model or url
<%=f.text_field :name%>
<%=f.submit "send"%>

<%=form_with model:%>の場合

出力結果

Parameters: {"authenticity_token"=>"[FILTERED]", "newname"=>{"name"=>"model"}, "commit"=>"send"}
# 2つめの"newname"=>{"name"=>"model"}に注目

<%=form_with url:%>の場合

出力結果

Parameters: {"authenticity_token"=>"[FILTERED]", "name"=>"url", "commit"=>"send"}
# 2つめの"name"=>"url" に注目

nameの部分が違うことがわかる

この時、<%=form_with url:%>の方はコントローラーのcreate以外でnewを呼び出す必要がない。➡重複しない

この際、アクションのcreateで用いるparams部分で注意が必要であり、

<%=form_with model:%>の場合

params.require(:newname)permit(:name)

<%=form_with url:%>の場合

params.permit(:name)

となる。 これはrequire部分で、2つ目のハッシュを指定するためである。

まとめ

controller内のmodel.newの重複を防ぐことを試していた。

<%=form_with url:%>を用いることで重複を防ぎいちいちmodel名.newを作成するのを防いだ。

この時、paramsに気を付けないとエラーとなる。