form_for の f.object って何だ?(Rails)

-2018.01.25 -Ruby・Rails
-,

久しぶりに書けました。
Railsをちょこちょこ勉強していて気になったf.objectについてメモ。

スポンサーリンク

form_forメソッドの基本形

SNS的な投稿フォームを作るとき、このような感じになるでしょうか?

# new.html.erb
<%= form_for(@message) do |f| %>
  <%= f.label :title, 'タイトル' %>
  <%= f.text_field :title %>
  
  <%= f.label :content, 'メッセージ' %>
  <%= f.text_field :content %>

  <%= f.submit '投稿' %>
<% end %>

form_forメソッドでブロック変数 f を利用してHTMLの <form> タグを生成します。
この時、modelのインスタンス @message を引数に持つことで
modelに基づいたフォームを作ることができます。

f.label, f.text_field でカラムを指定して、
@message 内のどのカラムに対する入力欄なのかを明示します。
最後に、f.submit で送信ボタンを生成します。

出力されるHTMLはこんな感じです。
おなじみのフォームですね。

<form class="new_message" id="new_message" action="/messages" accept-charset="UTF-8" method="post">
  
  <label for="message_title">タイトル</label>
  <input type="text" name="message[title]" id="message_title" />
  
  <label for="message_content">メッセージ</label>
  <input type="text" name="message[content]" id="message_content" />

  <input type="submit" name="commit" value="投稿" data-disable-with="投稿" />
</form>

今回触れたプログラム

エラーメッセージのDRYを考えて、10行目でパーシャルを利用した会員登録フォームです。

# new.html.erb
<div class="text-center">
  <h1>Sign up</h1>
</div>

<div class="row">
  <div class="col-md-6 col-md-offset-3">

    <%= form_for(@user) do |f| %>
      <%= render 'layouts/error_messages', model: f.object %>
      <div class="form-group">
        <%= f.label :name, 'Name' %>
        <%= f.text_field :name, class: 'form-control' %>
      </div>

      <div class="form-group">
        <%= f.label :email, 'Email' %>
        <%= f.email_field :email, class: 'form-control' %>
      </div>

      <div class="form-group">
        <%= f.label :password, 'Password' %>
        <%= f.password_field :password, class: 'form-control' %>
      </div>

      <div class="form-group">
        <%= f.label :password_confirmation, 'Confirmation' %>
        <%= f.password_field :password_confirmation, class: 'form-control' %>
      </div>

      <%= f.submit 'Sign up', class: 'btn btn-primary btn-block' %>
    <% end %>
  </div>
</div>
# layouts/_error_messages.html.erb
<% if model.errors.any? %>
  <div class="alert alert-warning">
    <ul>
      <% model.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
    </ul>
  </div>
<% end %>

f.objectって何だ?

今回気になったのは、その10行目にある f.object です。

そもそも、何の気なしに構文として覚えていたform_forメソッドですが、
ブロック変数 f って何を表しているんだ?と思い直し調べてみました。

  • fはフォームのインスタンス
  • form_forで@userを引数とすると種々メソッドが使える(モデルインスタンスの拡張?)
  • ブロック内で fから@userを取り出そうとしたら、f.objectとすればよい

んーなんだか分かったような分からなかったような。。

form_forメソッドの中で <%= f.inspect %> を実行してみました。
これで、fの中身を文字列で見ることが出来ます。
とても長いので大事なところだけ抜粋。

 @object=#<User id: nil, name: nil, email: nil, password_digest: nil, created_at: nil, updated_at: nil>

new.html.erbを見ているので、値が全てnilなのは良くて、
f.objectで、form_forメソッドの引数である @user を示していることがなんとなく分かりました!

つまり、下の2つはどっちを書いても同じであって、
変数の指定箇所を減らして運用工数を減らすことを考えると
上のほうが美しい、という問題だったのかな?

<%= form_for(@user) do |f| %>
      <%= render 'layouts/error_messages', model: f.object %>
<%= form_for(@user) do |f| %>
      <%= render 'layouts/error_messages', model: @user %>

記載・理解が違っていたらマサカリお願いします!
facebookアカウント
お問い合わせフォーム

          
    

スポンサーリンク

  
Scroll Up