form for タグ を理解する

はじめに

ここまで何度かアプリを作成する練習をしてきました。

そしてそのなかでフォーム作成をする機会が何度かあったんですが、

ちゃんと理解しないまま利用していたメソッド?タグ?がありました。

 

それが「form for」タグです。

いろんな記事を見たんですが、form for の説明が丁寧な記事ってなかなかなくって

よくわからないまま記載されてある記述をコピペしたりして

なんとかここまで実装してきました。

 

が、アプリケーションを作成する際にユーザー登録って必ず使うじゃないですか。

それなのにちゃんと理解できてないのって、まずいなって思ったんです。

 

なので今回はform forについて、ちゃんと理解していこうと思います。

 

どんなときに使うか?

そもそも form for ってどんな時に使えばいいか?

ー調べてみました。

 

form_forは入力フォームでデータを入力するときに使います。(ここまではわかる)

実際にはformタグ・ inputタグで入力フォームとして使うことができるんですが、

度々「form_for に変換した方がいい」と言われます。

これってなんでなんだろうって思ってたんですけど、

結論からいえばform_for タグを使ったほうが色々と楽なんだなーってことらしいです。

 

 

勝手にフォームアクションから適切なコントローラー内のアクションに移動してくれる

ビュー画面でフォームタグを作成すると、以下の感じになります。

 

f:id:lilybelly:20181006141128p:plain

 

例えばこれで、引数にuserのインスタンス変数を渡してあげるようになっています。

 

そして

@userで渡されたデータが

新しい情報の場合はuser#createに移って、

 createアクションでデータを作成保存してくれます。

既存の情報の場合はuser#updateに移って、

 updateアクションでデータの情報を更新してくれます。

 

これを特に記載せずに自動的にやってくれるっていうんだから

それは楽ですよね、、!

(デフォのcreate update 以外の動作を特定したい場合は、

 urlとmethodを書く必要があるらしいですが、、、)

 

 

勝手にパラメーターを生成してくれる 

コントローラー内でも便利みたいです。

ビューでform_forタグを使って書いたものが以下です。

 

f:id:lilybelly:20181006142256p:plain

 

form_tagのなかに、ネストして「f.〜」で書いてあるものがありますね。

このネストした部分がデータの新規作成・更新の時に

パラメーターとして生成してくれるみたいです。

(f.labelは表示される項目名みたいなもの、f.~fieldで書いてあるものが入力欄)

これで生成したuserのインスタンス変数に

ネスト内にあるnameやemailやpasswordなどの属性を入力してもらって、

それらをコントローラーへ引数として渡すことができます。

 

 

 

コントローラーへ移ると

実際にcreateアクション内で引数で渡したものを受け取り保存してくれます。

 

f:id:lilybelly:20181006143204p:plain

 

  ↑

こんな感じ

 

じゃあその中身はどうなっているかというと

上のform_forタグのネスト内で

「f.text_field: name」として属性値を設定してれば

パラメーターを生成してcreateメソッドに送ってるので

 

f:id:lilybelly:20181006143931p:plain

こんな風にユーザーモデルにネームというパラメータが入った状態になってるはずです。

 

なるほど、、ここまでまとめると、、、、

  • フォームタグから適切なアクションを識別して行ってくれる
  • コントローラー内へパラメーターを生成して送ってくれる

 

、、、めちゃ便利じゃん。頑張って使えるようにしよう。

 

実際にやってみる

今回はチャットアプリのビュー画面で、

グループ作成の際に情報を入力してもらうために

このform_tagを使いたいと思います。

 

f:id:lilybelly:20181006150857p:plain

 

実際にできたビュー画面です。

複雑になっちゃってるので、見にくくてすみません。

3行目のfomタグをform_forに変更して、groupの情報を登録したいので、@groupにします(ビューで変数をもってくるためには、コントローラーのアクションないに定義しなきゃいけません。ちゃんとあとでnewアクション内に定義します)

 

で、さっき説明したネストする f.~が12行目らへんにあります。

クラス名やplaceholderはこんな風に書くことができます。

 

ちなみに25行目はチェックボックスを表示させてます。

f:id:lilybelly:20181006151654p:plain

collection_check_boxを使う

f:id:lilybelly:20181006152022p:plain

さっきform_forタグの中のネスト内に f.~で属性を書くといいました。

 

これも基本的には同じです。f.collection_check_boxesで使えます。

 

ちなみにcollection_check_boxesの中には、

5つ引数がセットされています。


:group(第1引数)

:オブジェクト(form_forブロック配下では省略可能。上記では省略してます)

 


:user_ids (第2引数)

:メソッド(プロパティ?)


:User.all(第3引数)

:inputタグの元となるオブジェクト配列。配列の数だけinputタグが作成されます


:id(第4引数)

:作成されたinputタグのvalueとなる値を指定。今回の場合、各userのidが入力されます


:name(第5引数)

:作成されたinputタグのテキストとなる値を指定。

今回の場合、各userのnameが入力されます

 

こんな感じで、ユーザーidを管理しながら

チェックボックスにユーザー名を表示させることができました。

 

、、正直チェックボックスはまだ理解できてないので、

また今度記事にしていきたいと思います。

 

 

form_forから送られたデータを新規作成、保存するように設定する。

f:id:lilybelly:20181006154713p:plain

 

(この「@group.users << current_user」というのは、

選択するメンバーに自分は表示されないようになっているので

自動的に作成してる本人はグループに入れるようにしています。)

 

 

 

 

これでform_forタグからインスタンス変数を生成し、コントローラーアクションで新規作成・保存ができるようになりました。

 

 

なかなか難しいですが、

これを使うと便利なことがわかったので慣れるまで積極的に使っていこうと思います。