読者です 読者をやめる 読者になる 読者になる

Rails Webook

毎週更新。Railsプログラマがソフトウェア開発を効果的・効率的にするために、分かりやすく・使いやすい形でRailsに関する技術情報を記載!

Railsのform_forを使ったフォームのController,View,Modelの連携した処理フロー

Rails のform_forを使ったフォームのController、View、Modelの連携がよく分からない、何となく動いているけど理解していないからカスタマイズなどできそうにないといった方向け、form_forメソッドを中心としたMVCが連携する処理フローを説明していきます。

動作確認

・Rails 4.1.0

処理フロー概要

1. Controllerのnewメソッド/editメソッドでModelオブジェクトを生成しインスタンス変数(例:@userなど)に値を設定
2. Viewのform_forメソッドでModelオブジェクトのカラムを使用したフォームを作成し、表示する。
3. ユーザがサブミットすると、params変数に入力したパラメータがハッシュの形で設定されてControllerに届く。
4. Controllerのcreateメソッド /updateメソッドでparams変数でModelオブジェクトを作成/更新する。
という流れです。

新規登録フロー

前提

Userテーブルにはnameemailというカラムが存在していて、user.rbファイルが作成されている。

# app/models/user.rb
class User < ActiveRecord::Base
end

1. ControllerのnewメソッドでModelオブジェクトを生成しインスタンス変数に設定

# app/controllers/users_controller.rb
... 
def new
  # @user に空のModelオブジェクトを作成し、インタンス変数@userに設定
  # @userはViewでも使える
  # Controllerでrenderやredirect_toなどで明示的にレンダリングするViewをしていない場合は、
  # メソッド名のViewファイルがレンダリングされる(例:new => new.html.erb)
  @user = User.new
end
...

2. Viewのform_forメソッドでフォームを作成し、表示

# app/views/users/new.html.erb
...
# form_forに@userを渡すことにより、Userテーブルのnameとemailカラムの
# ラベルやテキストフィールドなどのinput要素を簡易に作成することができる
<%= form_for @user do |f| %>

  <div class="field">
    <%= f.label :name, "名前" %>
    <%= f.text_field :name %>
  </div>

  <div class="field">
    <%= f.label :email, "メールアドレス" %>
    <%= f.text_field :email %>
  </div>
  
  <div class="actions">
    <%= f.submit "登録する" %>
  </div>
<% end %>
...

作成された画面のフォーム部分は...

f:id:nipe880324:20140727165659p:plain

作成されたHTMLは...

input属性name属性に注目しといて下さい。これは、Model名とそのカラム名になっていることが分かると思います。

<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post"><div style="display:none"><input name="utf8" type="hidden" value="✓"><input name="authenticity_token" type="hidden" value="RIDGusRT/gJ2C+y+FKFV2P6rfN1mmNrQNWGX2sAtWrQ="></div>

  <div class="field">
    <label for="user_name">名前</label>
    <input id="user_name" name="user[name]" type="text">
  </div>

  <div class="field">
    <label for="user_email">メールアドレス</label>
    <input id="user_email" name="user[email]" type="text">
  </div>
  
  <div class="actions">
    <input name="commit" type="submit" value="登録する">
  </div>
</form>

3. ユーザがサブミットすると、params変数に入力したパラメータがハッシュの形で設定されてControllerに届く

先ほどの、input要素name属性をキーとしてハッシュ形式でparamsに設定されます。

params =
  {
    user: {  # params[:user] で { name: "鈴木", email: "suzu..." } を取得可能
      name: "鈴木",     # params[:user][:name] で値を取得可能
      email: "suzuki@example.com"   # params[:user][:email] で値を取得可能
    }
  }

4. Controllerのcreateメソッドでparams変数でModelオブジェクトを作成

# app/controllers/users_controller.rb
... 
def create
  @user = User.new(user_params)
  if @user.save
    # @userはuser_path(@user) に自動変換される
    redirect_to @user, notice: "ユーザ登録しました。"
  else
    # ValidationエラーなどでDBに保存できない場合 new.html.erb を再表示
    render 'new'
  end

  private
    # Rails4からStrongParamaterと呼ばれる機能が追加されました。
    # セキュリティのため、permitメソッドで許可したパラメータ名しか取得できません。
    def user_params
      params.require(:user).permit(:name, :email)
    end
end


以上です。