form_tagとform_forの違い


form_for

「モデルの新規インスタンスに値を追加して保存」したい場合はform_for

form_forは、特定の「モデル」を編集・追加するためのフォームを生成するヘルパーメソッド。
特定のテーブルにレコード(モデルクラスのインスタンス)だけを新規作成、更新するときに利用する。

このような特性があるので、form_tagとform_forは下記のように使い分ける。

■form_for: 任意のモデルに基づいたformを作るときに使う(投稿フォームなど)
→フォームに入力した情報をモデルを通じて、テーブルに追加・編集する
■form_tag: モデルに基づかないformを作るときに使う(検索フォームなど)
→検索は別にモデルに編集やインスタンスの追加をする必要はない

(使い方)

form_for.rb
<%= form_for(モデルクラスのインスタンス) do |f| %><% end %>

form_forは引数のインスタンスが何も情報を持っていなければ自動的にcreateアクションへ、すでに情報を持っている場合はupdateアクションへ自動的に振り分けてくれる。form_tagのようにルーティングパスを指定する必要がないのでラク。

モデルクラスのインスタンスはコントローラで予め定義しておくこと!

form_for内で使うメソッドは、f.htmlタグ名 :カラム名の形で指定

【form_forにおけるメソッドの例】

メソッド           用途           
f.label labelのlabelタグを表示 
f.text_field textのinputタグを表示
f.date_select モデルで設定したフィールドをselectタグで選べるようにして表示  
f.check_box checkboxのinputタグを表示
f.number_field numberのinputタグを表示
f.submit submitのinputタグを表示

参照URL:http://railsdoc.com/form

sample.rb
    <%= form_for [@product, @review] do |f| %>
          <div style="margin: 8px 0">
            <%= f.label :nickname, style: { 'margin-right' => 8 } %>
            <%= f.text_field :nickname, placeholder: 'nickname', value: '' %>
          </div>
          <div style="margin: 8px 0">
            <%= f.label :評価, style: { 'margin-right' => 8 } %>
            <%= f.number_field :rate, placeholder: '評価', value: 1, max: 10, min: 1, html: { class: "search__query", style: 'text-align: right;' } %>
          </div>
          <div style="margin: 8px 0">
            <%= f.text_area :review, placeholder: 'レビューを書いてね!', style: 'width: 100%;height: 300px;' %>
          </div>
          <div class="row">
            <div class="col10 push1">
              <%= button_tag type: "submit", class: "btn btn--block" do %>
              投稿する<i class="icon-arrow-right"></i>
              <% end %>
            </div>
          </div>
      <% end %>

1行目のform_forの引数が配列になっている。配列の1つ目の要素のインスタンスのidがパスの:product_idに入る。今回はパスのネストが2段階なので、form_forの引数のインスタンスは2つ。

form_forの引数について

resourcesを2回ネストした場合

routes.rb
resources :users do
  resources :products do
    resources :reviews
  end
end
controller.rb
def new
  @user = User.find(4)
  @product = Product.find(2)
  @review = Review.new
end
new.html.erb
<%= form_for ( [@user, @product, @review ] ) do |f| %>
  (中略)
<% end %>
送られるリクエスト
↓↓
# HTTPメソッド
POST
# パス
/users/4/product/2/reviews

form_tagとform_forでのパラメータへの保存方法の違い

binding.pryを使ってparamsを見るとよく分かるが、form_forはparamsのハッシュの中に別のハッシュが内包されており、ハッシュの二重構造が存在している状態になっている。

ターミナルで見るとこんな感じ
↓↓↓↓

>>>new.html.erb
<%= form_for(@book) do |f| %>
  <%= f.text_field :name %>
  <%= f.text_area :detail %>
<% end %>

>>>ターミナル
params
# { book: { name: "入力された名前", detail: "入力された詳細" } }

※上の例のbookはモデル名

なので、これらをハッシュをまずは分離してあげる必要がある。そこで使用するので、「require」メソッド。これを利用することで、ストロングパラメータを設定することができる。

<requireメソッド>
params.require(:モデル名).permit(:カラム名)
→これでparamsの中からモデル名(book)のハッシュ({ name: "入力された名前", detail: "入力された詳細" })を呼び出している

【参照URL】
https://qiita.com/tsubasakat/items/4ececaba4efc928c0792
https://www.sejuku.net/blog/13163