Ruby on Rails プログラミング 日記投稿サービスを1から作る

【Rails 初心者】newとcreateの違い 日記投稿サービスを作る#2

どうもこんにちは、みやちゃです!

前回の記事では、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アクションについて解説しました。

ここまでご覧いただきありがとうございます!

© 2024 とあるエンジニアの備忘録ブログ Powered by AFFINGER5