cre8cre8
AskMe♥

Railsのform_forの使い方が
リファレンス見てもいまいちわからなかったので
俺式に全力で整理してみた

  リファレンス
       見てもわからぬ
          form_for

この記事のすべてはこの4行集約しております。 (* コメント行は除外してます。)

ruby
1# URLで飛ばすとき
2form_for(@book, url: 'https://cre8cre8.com')
3# コントローラ名とアクション名で飛ばすとき
4form_for(@book, url: {controller: index, action:index })
5# ルーティングで定義したものでうまいこと飛ばすとき "$ rake routes" で確認できる
6form_for(@book, url: books_path)
7# HTTPメソッドを変更したいとき
8form_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
1form_for(@book, url: 'https://cre8cre8.com')

ね?簡単でしょ?
あ、ハードコードはちょっと...っという方。わかりました。他の書き方も用意されています。

ruby
1form_for(@book, url: {controller: index, action:index })

ハッシュに渡しているキーがすべてを語っていますが、 controller の箇所にコントローラ名を、 action の箇所にアクション名を記述するだけで、
あとは Rails がよろしくやってくれます。

もっとスマートに書きたい方。できます。 Rails はそのへんの紳士的な書き方もサポートしています。

ruby
1# この書き方をすると books/index へ飛ばされます。
2form_for(@book, url: books_path)

_path とはどこからでてきたんですか?っと疑問が出てきたと思います。
はい。私は初めて見た時そう思いました。作った記憶がありませんし、 books_path の books ってどこからでてきたのかと思いました。
しかも、 new_book_pathedit_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
6edit_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
1form_for(@book, url: 'http://cre8cre8.com', html: {method: 'GET'})

上記で GET メソッドになります。簡単ですね。
これで form_for が使えるようになると思います。

次回は私が出会った奇妙なform_forです。
最後までお読みいただいてありがとうございした。

次の記事 ≫
sh -c で実行したコマンドのログ出力方法
〜teeの優しく右手添え〜

いいねやコメントを送っていただけると中の人がしっぽ振って大喜びします♪

あなたへのおすすめの記事