Rails Tutorial 7章 ユーザー登録フォーム(フォームの作成・送信)


ユーザー登録フォーム


1、form_forを使う

Railsに元々あるヘルパーメソッド。

まず、登録フォームのアクションから設定

app/controllers/users_controller.rb
def new
  @user = User.new
end


んで、これがフォーム

app/views/users/new.html.erb
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">
    <%= form_for(@user) do |f| %>
      <%= f.label :name %>
      <%= f.text_field :name %>

      <%= f.label :email %>
      <%= f.email_field :email %>

      <%= f.label :password %>
      <%= f.password_field :password %>

      <%= f.label :password_confirmation, "Confirmation" %>
      <%= f.password_field :password_confirmation %>

      <%= f.submit "Create my account", class: "btn btn-primary" %>
    <% end %>
  </div>
</div>


2、フォームHTML


先ほど作成したフォームを理解するため、細かく見ていく。

<%= form_for(@user) do |f| %>
.
.
<% end %>

・do は、form_forが一つの変数を取るブロックを表す。
・fオブジェクトは、HTMLフォーム要素(textfieldとか)に対応するメソッドが呼び出されると、@userの属性を指定するために特別に設計されたHTMLを返す。


つまり、これでは

<%= f.label :name %>
<%= f.text_field :name %>

Userモデルのname属性を設定する、ラベル付きテキストフィールドを返す。

こんなHTMLを生成してるよ

<label for="user_name">Name</label>
<input id="user_name" name="user[name]" type="text" />




重要なのが、inputごとにあるname属性

これ

<input id="user_name" name="user[name]" - - - />
.
.
<input id="user_password" name="user[password]" - - - />


これは、Railsがnameの値を使って初期化したハッシュをparams変数経由で構成するもの。nameの値がparamsで受け取れる。んだと思う




次に、formタグ自身

<form action="/users" class="new_user" id="new_user" method="post">

action = " /users "
method = " post "  この二つが重要。
form_forはこれを勝手に生成してくれる。






3.1、ユーザー登録失敗

こんな感じで作る

createアクションでフォーム送信を受け付ける

User.newで新しいオブジェクトを作成

ユーザーを保存(または失敗)

再度、送信用のユーザー登録ページを表示





まず、createアクションを作る(途中まで)

app/controllers/users_controller.rb

def create
  @user = User,new(params[:user])
 if @user.save
   #保存の成功をここで扱う
 else
   render 'new'
 end
end

深く理解するため、デバック情報を参照してみる

"user" => { "name" => "Foo Bar",
            "email" => "foo@invalid",
            "password" => "[FILTERED]",
            "password_confirmation" => "[FILTERED]"
          }

ここでは、params[:user]に複数のハッシュが含まれている。フォーム送信の結果が、送信された値に対応する属性とともにuserハッシュに保存されている。
ハッシュのキーは、inputタグにあったnameの値。



ちなみに、この二つは同義

@user = User.new(params[:user])
@user = User.new(name: "Foo Bar", email: "foo@invalid",
                 password: "foo", password_confirmation: "bar")


けど、前者のコードではセキュリティ面で懸念があるっぽい。
そこで登場するのがStrongParameters


3.2、Strong Parameters

まず、マスアサインメントってやつ
次のコードみたいに、値のハッシュを使ってRubyの変数を初期化するもの

@user = User.new(params[:user])


マスアサインメントでは、name, emailとかの他に、actionやcontrollerといった全ての値が飛んでくる。


paramsハッシュ全体を初期化するのは危険すギル。マスアサインメント脆弱性(admin=管理者権限 があればparamsの中身を見れるし自由にシステムを操作できるっぽい)。
今は、マスアサインメントを使うとRailsが怒る。

そこで、StrongParametersを使用
これを使うことで、必須のパラメーターと許可されたパラメーターを指定することができる。って何?
 →簡単に言うと、DBへ入れたり更新したりする値を制限できるらしい


<使い方>
①requireでPOSTで受け取る値の設定
②permitで許可するカラムを設定

例えば、「user属性を必須にして、名前・アドレス・パスワード・パスワードの確認だけ更新許可したい!」ってとき

params.require(:user).permit(:name, :email, :password, :password_confirmation)


ここで、このパラメーターを使いやすくするため、巷では user_paramsとかいう外部メソッドが使われているらしい。
主に params[:user] の代わりとして使われる

@user = User.new(user_params)

これを、外部ユーザーに漏れないよう、privateに隠す

app/controllers/users_controller.rb
.
.
def create
  @uer = User.new(user_params)
  if @user.save
   #保存の成功をここで扱う
  else
   render 'new'
  end
end

private

  def user_params
    params.require(:user).permit(:name, :email, :password, :password_confirmation)
  end