どうもこんにちは、みやちゃです!
前回の記事では、indexアクションを定義し、ブラウザ上で投稿の一覧表示が見られるようにしました。
今回は、newアクションとcreateアクションを定義することによって、投稿機能を作ります。
目次
newとcreateの違い
newとcreateを定義しようとしたら、まず疑問が湧いていきます。
2つの違いはなんでしょうか。
newアクションは、
「投稿を新規作成するためのフォーム(書き込むところ)をviewに返すアクション」
createアクションは、
「投稿を新規作成するアクション」
です。
「newアクションで作成フォームをviewに表示させ、フォームに入力された情報がcreateアクションに送られて、データベースに書き加えられる」
といった感じでしょうかね。
なんとなく違いはわかりました。
実際にコードを書くことによってさらなる理解を期待します。
newアクション
newアクションを定義
posts_controller.rbを開き、以下のように記述します。
def new
@post = Post.new
end
そして、view/postフォルダに新しくnew.html.erbファイルを作成します。
new.html.erbに投稿フォームを書いていきましょう。
new.html.erbを開き、以下のように記述します。
<h1>投稿の作成</h1>
<%= form_with(model: @post, local: true) do |form| %>
<div>
<%= form.label :title %>
<%= form.text_field :title %>
</div>
<div>
<%= form.label :body %>
<%= form.text_area :body %>
</div>
<div>
<%= form.submit %>
</div>
<% end %>
form_withを使って、書きました。
form_withは、フォーム作成を支援するヘルパーです。
form_with及び、form_withの中身(label/text_field/text_area/submit)については、こちらの記事で詳しく解説しているのでそちらを参考にしてください。長くなるのでここでは省きます。
最低限のことだけ触れますと、form_withは、引数(@post)が情報を持っているかどうかでどのアクション(create、update)に情報が送信されるかが自動で変わります。
具体的には、
引数(@post)が
newで新規作成されたなら(情報を持たない)、createアクションに、
findなどで作成されたなら(既に何かしらの情報を持ってる)、updateアクションに
それぞれ自動で送信されます。
今回は、投稿フォームに入力された情報を自動でcreateアクションに送信してくれます。
ルーティングの設定
newアクションが定義できたので、ルーティングを設定しましょう。
routes.rbを開き、以下のように記述します。
get 'posts/new', to: 'posts#new', as: 'new_post'
この意味は、前回の記事でもやった通り、
「posts/new」というリクエスト(URL)があったら、postsコントローラーのnewアクションを呼び出す
という意味です。
asのオプションは、名前を設定できます。
「new_post」と設定したので、new_post_pathを使えば、newのページを呼び出すことができます。
(ちなみに、asオプションを設定しないと、「posts_new」になるみたいです。名前は、rake routesで確認可能 下でも触れます)
それではブラウザ(localhost:3000/posts/new)にアクセスしてみます。
いい感じにフォームができてますね。
では何かを打ち込んで、送信してみます。
route errorが出ました。
内容としては、
POSTメソッド(HTTPメソッドの1つ)の'/posts'というURLはありません。
という感じでしょうかね。
routes.rbに
「post 'posts/', to 〜〜〜」
のようなものは、まだ定義していないので当然ですね。
では定義しちゃいましょう。
createアクション
ルーティングの設定
createアクションのルーティングを設定します。
routes.rbを開いて、次のように記述します。
post 'posts/', to: 'posts#create'
この意味は、
POSTメソッド(HTTPメソッドの1つ)で、「posts/」というリクエストがあったら、postsコントローラーのcreateアクションを呼び出す。
です。
indexの時は、GETメソッドの「posts/」というリクエストを定義しました。
「get 'posts', to: 'posts#index'」こんな感じです。
今回は、投稿を”作成”するので、POSTメソッドですね。ここら辺は、HTTPメソッドについてで、前回の記事で詳しく解説しています。
ではブラウザを更新してみましょう。
すると、上のようなerrorが出ました。
内容としては、
posts_controllerには、「create」というアクションはない
という感じですね。controllerに、まだcreateアクションを定義していないので当然ですね。
いい感じにエラーが出てますね。うまくいっているようです。
createアクションを定義
では、posts_controller.rbにcreateアクションを定義しましょう。
posts_controller.rbを開き、以下のように記述します。
def create
@post = Post.new(post_params)
if @post.save
redirect_to posts_path
end
end
def post_params
params.require(:post).permit(:body, :title)
end
なんかnewに比べて書くことが多いですね。
1つ1つ見てみます。
先ほどはnewを定義しました。
newの定義の時にはなかった「(post_params)」がPost.newの横に追加されてます。
これはなんでしょうか。
これは「引数」です。
復習すると、
newアクションは、投稿を作成するためのフォームを返すだけなのに比べ、
createアクションは、実際にデータベースに投稿を作成します。
そのためには、作成するのに必要となるPostモデルのカラム(column)も値として与えてあげないといけません。
Postのcolumnは、bodyとtitleでしたね。
これらを引数として渡すために、post_paramsを別で定義しているのです。
post_params
ここでは、Postのパラメータを引数として渡すためのコードを記述します。
def post_params
params.require(:post).permit(:body, :title)
end
requireメソッドで、パラメータ群を指定し、
permitメソッドで、利用するパラメータを指定しています。
permitメソッドでは、送られる必要のない、もしくはパスワードなどの重要なパラメータを除外することができます。
これらのことは、ストロングパラメータと呼ばれています。
こちらの記事で詳しく解説しているので、参考にしてください。
そして、投稿が無事作成されたら、posts_path(indexのページ)に移動するということをif文を使って記述しています。(上の4行目)
redirect_toは、「redirect_to ページのパス(path)」のように記述することで、自動でそのページに移動できます。
上では、「if @post.save redirect_to posts_path」とあるので、
「もし@postが作成され保存されたら、posts_path(indexのページ)に移動しなさい」
という意味ですね。
また、このposts_pathは、先ほどルーティングの設定のところで、asオプションで名前がつけられるとやったやつですね。
それぞれのページがどんな名前になっているかは、terminalでrails routesコマンドで確認できます。
mbp:ibs_diary miyacha$ rake routes
Prefix Verb URI Pattern Controller#Action
posts GET /posts(.:format) posts#index
new_post GET /posts/new(.:format) posts#new
POST /posts(.:format) posts#create
prefixの欄ですね。これに「_path」をつけることで指定できます。(例 posts_path、new_post_path)
ブラウザを更新すると、エラー画面からindexの画面に移動し、四番目の投稿が追加されていることが確認できると思います。
ちゃんと表示されました。
まとめ
今回は、new/createアクションについて解説しました。
ここまでご覧いただきありがとうございます!