Railsのform_forの使い方が
リファレンス見てもいまいちわからなかったので
俺式に全力で整理してみた
リファレンス
見てもわからぬ
form_for
この記事のすべてはこの4行集約しております。 (* コメント行は除外してます。)
| ruby | |
|---|---|
| 1 | # URLで飛ばすとき |
| 2 | form_for(@book, url: 'https://cre8cre8.com') |
| 3 | # コントローラ名とアクション名で飛ばすとき |
| 4 | form_for(@book, url: {controller: index, action:index }) |
| 5 | # ルーティングで定義したものでうまいこと飛ばすとき "$ rake routes" で確認できる |
| 6 | form_for(@book, url: books_path) |
| 7 | # HTTPメソッドを変更したいとき |
| 8 | form_for(@book, url: 'http://cre8cre8.com', html: {method: 'GET'}) |
それでは解説に入ります。まずはサンプルプロジェクトを用意します。
| bash | |
|---|---|
| 1 | $ rails new form_for_sample --skip-bundle |
| 2 | $ cd form_for_sample |
| 3 | $ bundle install --path vendor/bundle |
| 4 | $ rails g scaffold book subject:string price:integer |
| 5 | $ rake db:migrate |
| 6 | $ rails s |
http://localhost:3000 にアクセスしてみてRailsのいつもの赤いページが
表示されましたら、サンプルプロジェクトの用意が完了です。
では、実際に form_for の使い方を整理してみます。
scaffold で作成した app/views/books/_form.html.erb の中身を見てみましょう。
| ruby | |
|---|---|
| 1 | <%= form_for(@book) do |f| %> |
| 2 | <% if @book.errors.any? %> |
| 3 | <div id="error_explanation"> |
| 4 | <h2><%= pluralize(@book.errors.count, "error") %> prohibited this book from being saved:</h2> |
| 5 | |
| 6 | <ul> |
| 7 | <% @book.errors.full_messages.each do |message| %> |
| 8 | <li><%= message %></li> |
| 9 | <% end %> |
| 10 | </ul> |
| 11 | </div> |
| 12 | <% end %> |
| 13 | |
| 14 | <div class="field"> |
| 15 | <%= f.label :subject %><br> |
| 16 | <%= f.text_field :subject %> |
| 17 | </div> |
| 18 | <div class="field"> |
| 19 | <%= f.label :price %><br> |
| 20 | <%= f.number_field :price %> |
| 21 | </div> |
| 22 | <div class="actions"> |
| 23 | <%= f.submit %> |
| 24 | </div> |
| 25 | <% end %> |
自動生成された view の1行目 <%= form_for(@book) do |f| %> に form_for が使われていますね。
他にも覚えるところはありますが、まずはここの使い方を整理してみましょう。
この箇所さえ抑えれば、あとはリファレンスを見てどうとでもできます。
まず、誤解を恐れずにいうと、 @book には ActiveRecord::Base のインスタンスをいれてください。
今回のサンプルプロジェクトでいうなれば、 app/models/book.rb です。
このbookクラスが、ただnewされただけなら新規作成になります。
ただnewされただけというのは、フォームからデータが送られていないことです。
そして、フォームからデータを送られてきた場合は、更新に遷移するように
勝手に form タグの遷移先のパスが生成されます。
HTMLで表すと、 <form action="ここと" method="この部分"> を Rails がよろしく勝手にやってくれます。
さて、このままですと、ちょっと不便な時があります。
例えば、好きなURLへ飛ばしたいときとか、ちょっと POST は勘弁なんだけと、なんか POST になっちゃてるとか...
そうですね。もうちょっと便利に書いてみましょう。
| ruby | |
|---|---|
| 1 | form_for(@book, url: 'https://cre8cre8.com') |
ね?簡単でしょ?
あ、ハードコードはちょっと...っという方。わかりました。他の書き方も用意されています。
| ruby | |
|---|---|
| 1 | form_for(@book, url: {controller: index, action:index }) |
ハッシュに渡しているキーがすべてを語っていますが、 controller の箇所にコントローラ名を、 action の箇所にアクション名を記述するだけで、
あとは Rails がよろしくやってくれます。
もっとスマートに書きたい方。できます。 Rails はそのへんの紳士的な書き方もサポートしています。
| ruby | |
|---|---|
| 1 | # この書き方をすると books/index へ飛ばされます。 |
| 2 | form_for(@book, url: books_path) |
_path とはどこからでてきたんですか?っと疑問が出てきたと思います。
はい。私は初めて見た時そう思いました。作った記憶がありませんし、 books_path の books ってどこからでてきたのかと思いました。
しかも、 new_book_path や edit_book_path やはたまた一見すると違いがわからない book_path なんてものもあります。
実はこれらは Rails のルーティングで定義したものが使われているのですね。
簡単に確認する方法としまして、
| bash | |
|---|---|
| 1 | $ rake routes |
| 2 | Prefix Verb URI Pattern Controller#Action |
| 3 | books GET /books(.:format) books#index |
| 4 | POST /books(.:format) books#create |
| 5 | new_book GET /books/new(.:format) books#new |
| 6 | edit_book GET /books/:id/edit(.:format) books#edit |
| 7 | book GET /books/:id(.:format) books#show |
| 8 | PATCH /books/:id(.:format) books#update |
| 9 | PUT /books/:id(.:format) books#update |
| 10 | DELETE /books/:id(.:format) books#destroy |
Prefix の行に注目です。ここに書いてあるやつ + _path で遷移先のURLが自動的に Rails がよろしくやってくれます。
すごく便利ですね。わかってからはよく使っています。
さて、最後のどうあがいても POST で飛ぶ時のHTTPメソッドの変更方法ですが、
| ruby | |
|---|---|
| 1 | form_for(@book, url: 'http://cre8cre8.com', html: {method: 'GET'}) |
上記で GET メソッドになります。簡単ですね。
これで form_for が使えるようになると思います。
次回は私が出会った奇妙なform_forです。
最後までお読みいただいてありがとうございした。