10
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Ruby on rails]新規投稿機能の実装手順と仕組みについて

Last updated at Posted at 2021-04-29

自己紹介

初めまして。現在24歳で未経験からエンジニアになるためにプログラミングを勉強しています。2021年5月からはDMMWEBCAMPを受講します。よろしくお願いします。

#1. はじめに
自分が学習していく中で、すごくつまずいたRailsの「投稿の仕組み」について調べてみました。
この記事では、実際に投稿機能の実装をするためのコードの書き方、また、Railsのコントローラーのアクションが行われた時の、ターミナルのログの意味について説明していきます。

目次

  1. テーブルの作成
     ・dbに保存するためのモデルを作成
     ・テーブルを作成するためのマイグレーションファイルを作成

  2. データベースに反映させる

  3. controller内にnewアクションを定義

  4. viewファイルに入力フォームを作成

  5. 投稿ボタンが押されたら反応するcreateアクションを実装

  6. '/posts'にPOSTリクエストを送信

  7. createアクションを実行し、投稿フォーム内のデータをデータベースに保存

  8. 新規投稿がindex.html.erbで表示され、ユーザーの画面に表示される

#1. テーブルの作成
では、データベースに投稿したいデータを保存するためのモデルを作成します。
その後、テーブルを作成するためのマイグレーションファイルを作成します。
最後に、マイグレーションを実行してデータベースにテーブルを作成します。
まずは、データの格納先である、データベースに値を保存するために必要なモデルを作ります。
モデルは「データベース」そのものではなく、データベースに対応した箱を作り、その取扱い方法を記述するというものです。

記述の仕方

Model名は大文字から始まる単数形にします。
今回は投稿のタイトルをtitileカラム、本文のbodyカラムの2種類を作成します。
※1つ1つのデータの格納場所をカラムと言います。
データ型も指定する必要があり、
titleは255文字以内としてString型bodyはそれ以上入力する可能性があるのでtext型にします。

console
$ rails g model Post title:string body:text

上記のコマンドを実行すると、モデル、マイグレーション、テストファイルが作成されます。
マイグレーションファイルはデータベースを変更するための指示書のようなものです。
上記のコマンドでは下記の内容のファイルになります。

db/_create_posts.rb
class CreatePosts < ActiveRecord::Migration[6.1]
def change
    create_table :posts do |t|
      t.string :title
      t.text :body
      t.timestamps
    end
  end
end

#2. データベースに反映させる
1のままではデータベースに反映されていません。
記入したマイグレーションファイルを反映させるには、下記のコードをターミナルで実行します。
すると、データベースにテーブルが作成され、カラムが追加されます。

確認方法

db/schema.rbというファイルをみると、ここに追加されていることでデータベースに反映されたことが確認できます。

console
 $ rails db:migrate
db/migrate/20210419121504_create_posts

ActiveRecord::Schema.define(version: 2021_04_19_121504) do
  create_table "posts", force: :cascade do |t|
    t.string "title" #titleがマイグレーションされていることがわかります。
    t.text "body"    #bodyがマイグレーションされていることがわかります。
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end
end

#3. controller内にnewアクションを定義

app/controllers/posts_controller.rb
class PostsController < ApplicationController
  def new
    @post = Post.new #空のインスタンスを生成
  end
end

では、app/controllers/posts_controller.rbのnewアクションで、新規投稿画面の表示に必要な準備をします。
「Post.new」と記述するとインスタンスが生成され、インスタンス変数@postに代入されてviewで利用できるようになります。
次で記述するapp/views/posts/new.html.erbのform_withに空のモデルが代入されたインスタンス変数を渡すと、フォームとPostモデルが関連づけられ投稿できるようになります。

※インスタンス変数とは

クラスのオブジェクト(インスタンス)がもつ変数の1つです。
コントローラのインスタンス変数をViewと共有することで、コントローラからViewへのデータの受け渡しを行うことができます。
インスタンス変数に代入した値は、そのオブジェクトがある限り、オブジェクトとともに存在し続けます。
また、インスタンス変数の名前には、先頭に必ず@(アットマーク)を付けます。

#4. viewファイルに入力フォームを作成
では、form_withを利用して、投稿を表示させるフォームを作成していきます。
編集するのは、views/posts/new.html.erbのファイルです。
まず、投稿を新規作成するには、form_withの引数に渡す必要があるため、入力フォームを作成していきます。
入力フォームはform_withを使用することにより簡単にデータベースに保存ができます。

/views/posts/new.html.erb
<%= form_with model: @post, local: true do |form| %>

<p><%= form.label :title %><br>
<%= form.text_field :title %> #titleの入力フォーム生成
</p>

<p><%= form.label :body %><br>
<%= form.text_area :body %> #bodyの入力フォーム生成
</p>

<p><%= form.submit %> #送信ボタンを生成
</p>

<% end %>

#5. 投稿ボタンが押されたら反応するcreateアクションを実装
では、app/controllers/posts_controller.rbにフォームから送られてきたデータを保存する処理createアクション、送られてきたデータを受け取るためのpost_paramsを定義していきます。

app/controllers/posts_controller.rb
def create
  @post = Post.new(post_params) #データを新規登録するためのインスタンス生成
  @post.save #データをデータベースに保存するためのsaveメソッド実行
  redirect_to action: 'index' #トップ画面へリダイレクト
end

private
  def post_params #ストロングパラメータ
    params.require(:post).permit(:title, :body) #パラメーターのキー
  end
 end

6.URL '/posts'にPOSTリクエストがサーバーに送信

では、実際にcreateアクションが押され、裏では何が起きているかを説明していきます。
titleフォーム、bodyフォームに内容を記述し投稿ボタンを押すと、まずPOSTメソッドの'/posts'といわれるところに送信されます。

HTTPメソッドの役割について

GET ページの取得
POST データの作成・登録
PUT(PATCH) データの更新
DELETE データの削除

投稿ボタンが押された時のターミナルの状況

console
1.Started POST "/posts" for ::1 at 2021-04-19 12:05:00 +0900
2.Parameters: {"authenticity_token"=>"[FILTERED]", "post"=>{"title"=>"タイトル", "body"=>"ボディー"}, "commit"=>"Create Post"
3.TRANSACTION (0.1ms)  begin transaction
    app/controllers/posts_controller.rb:13:in `create'

1行目について

POSTと言うリクエストが'/posts'と言うURLに対して行われたと言う意味です。
投稿すると'/posts'と言うURLに対して指令が出されます。ここのルーティングはroutes.rbで設定されています。
ターミナルでrails routesと入力、実行してもらうとposts_pathにはGETPOSTの2種類の役割があることがわかります。
posts_pathに対してgetをするとposts#indexアクションが呼び出され、
また、posts_pathに対してpostをするとposts#createアクションが呼び出されます。
そして、今回はform_withで自動的にHTMLのフォームタグが生成され、methodの部分がpostになっているのでPOST通信が行われています。

2行目について

次に、createアクションが反応すると、先ほどposts_controllerのnewアクションで定義した、
@postと言う変数にPost.newが渡されます。さらに@postは(post_params)と言う引数を持っています。
post_paramsと言うのはRailsで送られてきた値を受け取るためのメソッドで、privateで定義されているリクエストとともに送られてくる情報のことをいいます。

3行目について

データベースに変更をくわえる手続きを「TRANSACTION」、'create'はposts_controllerでのcreateアクションで行われているという意味で、正常に投稿が行われたと言うことを表しています。

※privateについて

このprivateでは何が定義されているかというと上記の(:post)と言うパラメーターのキーの中にさらに(:titleと:body)のキーを許可するということが書いてあります。

ストロングパラメータについて

requireメソッドを使用する事で、params内の特定のキーに紐付く値だけを抽出する事ができます。今回で言う(:post)
そのため、引数には取り出したい値のキーを指定する必要があります。permitメソッドを使用する事で、許可された値のみを取得することができます。(:title, :body)
#7. createアクションを実行投稿フォーム内のデータをデータベースに保存
そして、createアクションで上から順にユーザーからのデータを@postに代入し、@post.saveでデータベースへ保存をします。redirect_to action: 'index' でトップ画面へリダイレクトをします。

8.新規投稿がindex.html.erbで表示され、ユーザーの画面に表示される

new.html.erbで投稿した内容をindex.html.erbで確認し、終了となります。

9.感想

この記事は、新規投稿の実装に困っている方の役に立ちたいという気持ちで書いてみました。
また、人にわかるように意識して書くことで、曖昧だった部分が整理できました。新規投稿についてもわかっているつもりでしたが、いざ、説明してみるとわかっていない部分、曖昧な部分が多くあることに気づき、正しい知識を付ける良いきっかけになりました。記事を書くことで人に説明するという意味も、理解することができました。

10
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?