概要
form系ヘルパーではフォームの入力がparams
変数にセットされるが、一般には以下の様な流れで入力パラメーターを利用する。
form_with/form_for
で読み込んだパラメーターをモデルにセットする- モデルへのパラメーターのセットは、慣習的に
private
のメソッドを準備して、それを介する - 各パラメーターは、モデルインスタンスのプロパティーとして参照・利用
モデルによるフォームデータの取得も参照。
例示
基本構造
流れ
- トップページに入力フォームを表示
/top
app/controllers/pages_controller#top
app/views/pages/top.html.erb
- フォーム入力を
pages
コントローラーのinput
アクションへ送信app/controllers/pages_controller#input
input
アクションでフォーム入力をUser
モデルインスタンスに格納して表示
入力フォーム
form_with
による以下のようなフォームを例にする。フォームビルダーのtext_field
とpassword_field
に入力された値が送信される。
1 2 3 4 5 |
<%= form_with(model: @user, url: input_path) do |form| %> <%= form.text_field(:name, placeholder: "名前を入力") %> <%= form.password_field(:password, placeholder: "パスワードを入力") %> <%= form.submit("送信") %> <% end %> |
注意点
form_with
はデフォルトでajaxによるフォーム送信となり、ページ全体がレンダリングされない。HTMLとして送信してレンダリングするには、パラメーターにlocal: true
を指定する。
<%= form_with(url:/model: ***, local: true) %>
モデルとデータベース
データを扱うモデルは以下で生成し、マイグレートしてテーブルを作成しておく
1 |
[vagrant@vagrant testapp]$ rails generate model user name:string password:string |
テーブル
1 2 3 4 5 6 7 8 9 10 11 |
mysql> desc users; +------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+----------------+ | id | bigint(20) | NO | PRI | NULL | auto_increment | | name | varchar(255) | YES | | NULL | | | password | varchar(255) | YES | | NULL | | | created_at | datetime | NO | | NULL | | | updated_at | datetime | NO | | NULL | | +------------+--------------+------+-----+---------+----------------+ 5 rows in set (0.00 sec) |
コントローラー
以下の枠組みでコントローラーを生成。ビューのform_withでモデルを使うため、Userインスタンスを生成している。
1 2 3 4 5 6 7 8 9 |
class PagesController < ApplicationController def top @user = User.new end def input # 入力時の処理 end end |
ルーティング
- アプリケーション起動時にtopページを表示
- 入力POST時にinputアクションへルーティング
1 2 3 4 |
Rails.application.routes.draw do root to: 'pages#top', as: :top post 'input', to: 'pages#input', as: :input end |
入力データのモデルへのセット
コントローラーに以下に様に追記。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
class PagesController < ApplicationController def top @user = User.new end def input puts "---------- form input ----------" user = User.new(user_params) p user p user.name p user.password redirect_to top_path and return end private def user_params params.require(:user).permit(:name, :password) end end |
要点は次のとおり。
パラメーターを引数にしてモデルインスタンスを与える。
変数 = モデルクラス.new(モデル名_params)
引数はモデルに与えるparams
を返すメソッドで、慣習としてメソッド名の付け方、praivate
宣言、require
とpremit
によるパラメーター取得が定まっている。
params.require(:モデル名).permit(:要素名, ...)
モデルにパラメーターがセットされた後は、要素名と同じモデルのプロパティーで値を取得。
コンソールの出力部分は以下のとおり
1 2 3 4 5 6 7 8 9 10 |
Started POST "/input" for 10.0.2.2 at 2021-03-13 09:47:19 +0900 Cannot render console from 10.0.2.2! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255 Processing by PagesController#input as JS Parameters: {"utf8"=>"✓", "authenticity_token"=>"o3M9kpQpW10kA+lAocHDdvsgFf3BdIgutcqGaapRBVqkuAu3eu0j5k6jhZHEbU44n43Y81cuicBjL0UeuLrFyA==", "user"=>{"name"=>"NAME", "password"=>"[FILTERED]"}, "commit"=>"送信"} ---------- form input ---------- #<User id: nil, name: "NAME", password: "PASSWORD", created_at: nil, updated_at: nil> "NAME" "PASSWORD" Redirected to http://localhost:3000/ Completed 200 OK in 3ms (ActiveRecord: 0.0ms) |
require/permitメソッド
フォームの入力をモデルにセットする際、require
~permit
でパラメーターを指定している。
たとえば悪意のあるユーザーによってPOSTされる要素が追加された場合でも、必要なパラメーターのみを参照・変更することができる。
そして上述のように、一般的にはrequire
~permit
のメソッドチェーンをprivate
メソッドでラップして使う。