はじめに
form_withをつかった投稿機能は、Rails 初学者がつまづきやすいポイントかと思います!
本記事では form_withを使った入力フォームの作成 、ストロングパラメータ、データの保存までを解説していきます。
図を織り交ぜていますので、イメージをつかみつつ理解を深めていきましょう
動作環境
- Ruby 2.6.7
- Rails 5.2.7 (動作としてはrails6系でも同様です)
実装する機能・仕様
フォームでタイトルと内容を入力し、データベースに保存する。
Blogモデルにtitle、bodyカラムを準備。
form_withを用いて入力データを送信する
new.html.erbにてフォームを以下のように作成していきます。
def new
@blog = Blog.new
end
<h1>Blogs#new</h1>
<%= form_with model: @blog, local: true do |f| %>
<!--タイトル入力フォーム生成-->
<%= f.label :title %><br>
<%= f.text_field :title %><br>
<!--内容入力フォーム生成-->
<%= f.label :body %><br>
<%= f.text_area :body %><br>
<!--投稿ボタン生成-->
<%= f.submit %>
<% end %>
入力フォームのイメージ
Blog.new
の記述がありますが、これはBlogの新しい箱を作るイメージになります。このBlogの箱の中には空のtitle、bodyの箱を持っています。この空の箱をインスタンス変数@blog
に格納して、フォームヘルパー(form_with)に渡していきます。
フォームヘルパーとは
フォームヘルパーは入力フォームを簡単に作成できるように、あらかじめメソッド(処理)を用意してくれているものです。 f.text_fieldやf.text_area、f.submitなどがその例です。フォームをヘルパーなしで書こうとするとなかなか面倒になるので、とてもありがたい存在です文字や値を入力したのちにCreate Blog
のボタンを押すと、フォームヘルパーは入力値を該当する箱に入れていきます。
この作業を経てパラメータの一つが生成され、次にcreateアクションへ送信していきます。イメージとしては荷物パッキングをして次のアクションまで配送するイメージです。
パラメータとは
ここで、パラメータについて少し触れます。
パラメータとは基本的にはアクション間で受け渡しされるデータのことを指します。
どのような情報が渡されているのかはターミナルで確認することができます。titleに"hoge"、bodyに"fuga"を入力してターミナルを確認すると以下のようになります。(一部抜粋)
Started POST "/blogs" for ......
:
Processing by BlogsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"..", "blog"=>{"title"=>"hoge", "body"=>"fuga"}, "commit"=>"Create Blog"}
:
:
今回はこの中でも
Parameters: {"utf8"=>"✓", "authenticity_token"=>"..", "blog"=>{"title"=>"hoge", "body"=>"fuga"}, "commit"=>"Create Blog"}
がパラメータになります。 『"〇〇"=>"××"』を一つのまとまりと考えます。上記を箱のイメージであらわすと
となります。箱の中にそれぞれ矢印の右辺の情報が入っているイメージです。
このように、先ほど入力した情報がBlogの箱の中のtitleとbodyに格納されて、送信されていることが確認できます。
フォームの送信後createアクションでの挙動
ここからはcreateアクション内での処理を説明していきます。
def create
# ストロングパラメータで入力された値を取得
@blog = Blog.new(blog_params)
# 保存
@blog.save
# 保存後詳細ページに遷移
redirect_to blog_path(@blog)
end
private
# ストロングパラメータ
def blog_params
params.require(:blog).permit(:title, :body)
end
送られてきた箱をそのまま保存したい!!となりますが、railsではアクションごとに新しい箱を作成して移し替える作業を行う必要があります
Blog.new(blog_params)
のBlog.new()
関しては前章の考え方と同様に、空の箱を作るイメージです。
かっこの中身は空の箱の中に、値をはじめから入れたいときに入力します。
ストロングパラメータ
今回はフォームで入力した値を空の箱に入れていきたいので、ここでストロングパラメータを定義したblog_params
を呼び出しています。
params.require(:blog).permit(:title, :body)
は3つに分割して考えていきます。
-
params
パラメータ全体を呼び出します。 -
.require(:blog)
パラメータの中で、どの要素(大きな箱)を選択するかを宣言します。今回の場合、4つの箱(utf8, authenticity_token, blog, commit)の中からblogを選択するという意味になります。 -
.permit(:title, :body)
選択した要素(大きな箱)内に含まれるパラメータの中でどの情報の保存を許可するのかを選択します。今回の場合、blogの箱の中にあるtitleとbodyについて保存するという意味になります。
ストロングパラメータはなぜ必要?
ストロングパラメータを設定することで、**不要な情報が保存されることを防ぎます**。 仮に悪意のあるユーザーがtitle、body以外の箱を自分で作って送信してきたとします。ストロングパラメータを設定していなかった場合、データベースにはそのカラムは存在していないので、その情報を保存するときにエラーを吐いてしまいます。ストロングパラメータで、必要な情報のみを選別しているといことになります。システムの根幹にもなるので、他の場所から呼び出して書き換えができないようにprivate下に書くことが一般的です。これらをまとめると、Blog.new(blog_params)
は『送られてきたパラメータの中から、blogの中のtitleとbodyを取り出して、新しい箱に入れる』ということになります。したがって、createアクションのイメージを描くと以下のようになります。
これでフォームの入力~データの保存が完了です!
おわりに
今回はフォームの入力から保存までの流れを図メインでまとめてみました!
イメージはつかめましたでしょうか?
少しでも参考になればと思います